blob: 27df76ee9363f903207564f7a850ec641175ff9e [file] [log] [blame]
/*
* 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"
#include <algorithm>
// 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
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
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_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("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_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceProperties2KHR GetPhysDevProps2 = instance.load("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, 1U);
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.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
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();
PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("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, 1U);
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));
}
{ // Do the same logic but have the application forget to use 1.1 and doesn't enable the extension - should emulate the call
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("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, 1U);
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));
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("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, 1U);
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));
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA, 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);
PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("vkGetPhysicalDeviceProperties2");
ASSERT_NE(GetPhysDevProps2, nullptr);
PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2KHR = instance.load("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, 1U);
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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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});
}
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();
PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = instance.load("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
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;
}
// Test vkGetPhysicalDeviceFeatures2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevFeats2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
ASSERT_EQ(GetPhysDevFeats2KHR, nullptr);
}
// Test vkGetPhysicalDeviceFeatures2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevFeatsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
ASSERT_EQ(GetPhysDevFeats2KHR, 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_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
ASSERT_NE(GetPhysDevFeats2KHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1U);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
GetPhysDevFeats2KHR(physical_device, &feats2);
ASSERT_EQ(feats, feats2);
}
// Test vkGetPhysicalDeviceFeatures2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevFeats2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
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});
env.get_test_icd(0).physical_devices.back().set_api_version(VK_API_VERSION_1_1);
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();
PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("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, 1U);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
GetPhysDevFeats2(physical_device, &feats2);
ASSERT_EQ(feats, feats2);
}
{ // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("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, 1U);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
GetPhysDevFeats2(physical_device, &feats2);
ASSERT_EQ(feats, feats2);
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("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, 1U);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
GetPhysDevFeats2(physical_device, &feats2);
ASSERT_EQ(feats, feats2);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA, 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);
PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysDevFeats2KHR = instance.load("vkGetPhysicalDeviceFeatures2KHR");
ASSERT_NE(GetPhysDevFeats2KHR, nullptr);
PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("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, 1U);
VkPhysicalDeviceFeatures feats{};
instance->vkGetPhysicalDeviceFeatures(physical_device, &feats);
VkPhysicalDeviceFeatures2KHR feats2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
GetPhysDevFeats2KHR(physical_device, &feats2KHR);
ASSERT_EQ(feats, feats2KHR);
VkPhysicalDeviceFeatures2 feats2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
GetPhysDevFeats2(physical_device, &feats2);
ASSERT_EQ(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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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});
}
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();
PFN_vkGetPhysicalDeviceFeatures2 GetPhysDevFeats2 = instance.load("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_EQ(feats, feats2);
}
}
// Fill in random but valid data into the format properties struct for the current physical device
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_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
instance.load("vkGetPhysicalDeviceFormatProperties2KHR");
ASSERT_EQ(GetPhysDevFormatProps2KHR, nullptr);
}
// Test vkGetPhysicalDeviceFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevFormatPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
instance.load("vkGetPhysicalDeviceFormatProperties2KHR");
ASSERT_EQ(GetPhysDevFormatProps2KHR, 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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
instance.load("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, 1U);
VkFormatProperties props{};
instance->vkGetPhysicalDeviceFormatProperties(physical_device, VK_FORMAT_R4G4_UNORM_PACK8, &props);
VkFormatProperties2 props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
GetPhysDevFormatProps2KHR(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.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevFormatProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_API_VERSION_1_1));
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});
env.get_test_icd(0).physical_devices.back().set_api_version(VK_API_VERSION_1_1);
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();
PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("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, 1U);
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);
}
{ // Do the same logic but have the application forget to enable 1.1 and doesn't enable the extension
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("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, 1U);
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);
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("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, 1U);
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);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("vkGetPhysicalDeviceFormatProperties2");
ASSERT_NE(GetPhysDevFormatProps2, nullptr);
PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysDevFormatProps2KHR =
instance.load("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, 1U);
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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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});
}
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();
PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysDevFormatProps2 = instance.load("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
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_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2 =
instance.load("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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2KHR =
instance.load("vkGetPhysicalDeviceImageFormatProperties2KHR");
ASSERT_EQ(GetPhysDevImageFormatProps2KHR, 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_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2KHR =
instance.load("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, 1U);
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, GetPhysDevImageFormatProps2KHR(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.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevImageFormatProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
instance.load("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, 1U);
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);
}
{ // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
instance.load("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, 1U);
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);
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
instance.load("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, 1U);
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);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
instance.load("vkGetPhysicalDeviceImageFormatProperties2");
ASSERT_NE(GetPhysDevImageFormatProps2, nullptr);
PFN_vkGetPhysicalDeviceImageFormatProperties2KHR GetPhysDevImageFormatProps2KHR =
instance.load("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, 1U);
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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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});
}
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();
PFN_vkGetPhysicalDeviceImageFormatProperties2 GetPhysDevImageFormatProps2 =
instance.load("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_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
instance.load("vkGetPhysicalDeviceMemoryProperties2KHR");
ASSERT_EQ(GetPhysDevMemoryProps2KHR, nullptr);
}
// Test vkGetPhysicalDeviceMemoryProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevMemoryPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
instance.load("vkGetPhysicalDeviceMemoryProperties2KHR");
ASSERT_EQ(GetPhysDevMemoryProps2KHR, nullptr);
}
// Fill in random but valid data into the memory data struct for the current physical device
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;
}
}
// 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_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
instance.load("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, 1U);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2KHR(physical_device, &props2);
ASSERT_EQ(props, props2);
}
// Test vkGetPhysicalDeviceMemoryProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevMemoryProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("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, 1U);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_device, &props2);
ASSERT_EQ(props, props2);
}
{ // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("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, 1U);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_device, &props2);
ASSERT_EQ(props, props2);
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("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, 1U);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_device, &props2);
ASSERT_EQ(props, props2);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("vkGetPhysicalDeviceMemoryProperties2");
ASSERT_NE(GetPhysDevMemoryProps2, nullptr);
PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysDevMemoryProps2KHR =
instance.load("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, 1U);
VkPhysicalDeviceMemoryProperties props{};
instance->vkGetPhysicalDeviceMemoryProperties(physical_device, &props);
VkPhysicalDeviceMemoryProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2};
GetPhysDevMemoryProps2(physical_device, &props2);
ASSERT_EQ(props, props2);
VkPhysicalDeviceMemoryProperties2KHR props2KHR{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR};
GetPhysDevMemoryProps2KHR(physical_device, &props2KHR);
ASSERT_EQ(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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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});
}
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();
PFN_vkGetPhysicalDeviceMemoryProperties2 GetPhysDevMemoryProps2 = instance.load("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_EQ(props, props2);
}
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
instance.load("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
ASSERT_EQ(GetPhysDevQueueFamilyProps2KHR, nullptr);
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
instance.load("vkGetPhysicalDeviceQueueFamilyProperties2KHR");
ASSERT_EQ(GetPhysDevQueueFamilyProps2KHR, nullptr);
}
// Fill in random but valid data into the queue family data struct for the current physical device
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 == 0;
}
return static_cast<uint32_t>(props.size());
}
// 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_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
instance.load("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, 1U);
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;
GetPhysDevQueueFamilyProps2KHR(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});
GetPhysDevQueueFamilyProps2KHR(physical_device, &ret_fam_2, props2.data());
ASSERT_EQ(props, props2);
}
// Test vkGetPhysicalDeviceQueueFamilyProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevQueueFamilyProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
instance.load("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, 1U);
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_EQ(props, props2);
}
{ // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
instance.load("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, 1U);
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_EQ(props, props2);
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
instance.load("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, 1U);
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_EQ(props, props2);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
instance.load("vkGetPhysicalDeviceQueueFamilyProperties2");
ASSERT_NE(GetPhysDevQueueFamilyProps2, nullptr);
PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR GetPhysDevQueueFamilyProps2KHR =
instance.load("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, 1U);
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_EQ(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_EQ(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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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});
}
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();
PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysDevQueueFamilyProps2 =
instance.load("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_EQ(props, props2);
}
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where nothing supports it.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2KHRNoSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
ASSERT_EQ(GetPhysDevSparseImageFormatProps2KHR, nullptr);
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2KHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
ASSERT_EQ(GetPhysDevSparseImageFormatProps2KHR, nullptr);
}
// Fill in random but valid data into the sparse image format data struct for the current physical device
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);
}
}
// 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_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
instance.load("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, 1U);
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, 0U);
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, 0U);
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;
GetPhysDevSparseImageFormatProps2KHR(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});
GetPhysDevSparseImageFormatProps2KHR(physical_device, &info2, &sparse_count_2, props2.data());
ASSERT_EQ(sparse_count_1, sparse_count_2);
ASSERT_EQ(props, props2);
}
// Test vkGetPhysicalDeviceSparseImageFormatProperties2 where instance supports, an ICD, and a device under that ICD
// also support, so everything should work and return properly.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevSparseImageFormatProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
instance.load("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, 1U);
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, 0U);
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, 0U);
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_EQ(props, props2);
}
{ // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
instance.load("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, 1U);
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, 0U);
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, 0U);
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_EQ(props, props2);
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
instance.load("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, 1U);
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, 0U);
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, 0U);
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_EQ(props, props2);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
instance.load("vkGetPhysicalDeviceSparseImageFormatProperties2");
ASSERT_NE(GetPhysDevSparseImageFormatProps2, nullptr);
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR GetPhysDevSparseImageFormatProps2KHR =
instance.load("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, 1U);
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, 0U);
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, 0U);
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_EQ(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_EQ(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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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});
}
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();
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 GetPhysDevSparseImageFormatProps2 =
instance.load("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, 0U);
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, 0U);
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_EQ(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_2_EXPORT_ICD_GPDPA));
env.get_test_icd(0).physical_devices.push_back({});
InstWrapper instance(env.vulkan_functions);
instance.CheckCreate();
PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR =
instance.load("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
ASSERT_EQ(GetPhysicalDeviceExternalBufferPropertiesKHR, nullptr);
}
// Test vkGetPhysicalDeviceExternalBufferPropertiesKHR where instance supports it, but nothing else.
TEST(LoaderInstPhysDevExts, PhysDevExtBufPropsKHRNoICDSupport) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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);
PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR =
instance.load("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
ASSERT_EQ(GetPhysicalDeviceExternalBufferPropertiesKHR, nullptr);
}
// Fill in random but valid data into the external memorydata struct for the current physical device
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);
}
// 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_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR GetPhysicalDeviceExternalBufferPropertiesKHR =
instance.load("vkGetPhysicalDeviceExternalBufferPropertiesKHR");
ASSERT_NE(GetPhysicalDeviceExternalBufferPropertiesKHR, nullptr);
uint32_t driver_count = 1;
VkPhysicalDevice physical_device;
ASSERT_EQ(VK_SUCCESS, instance->vkEnumeratePhysicalDevices(instance, &driver_count, &physical_device));
ASSERT_EQ(driver_count, 1U);
VkPhysicalDeviceExternalBufferInfoKHR info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR};
VkExternalBufferPropertiesKHR props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR};
GetPhysicalDeviceExternalBufferPropertiesKHR(physical_device, &info, &props);
ASSERT_EQ(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.
// Also check if the application didn't enable 1.1 and when a layer 'upgrades' the api version to 1.1
TEST(LoaderInstPhysDevExts, PhysDevExtBufProps2Simple) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
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();
PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
instance.load("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, 1U);
VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().external_memory_properties, props.externalMemoryProperties);
}
{ // Now do the same logic but the application didn't enable 1.0 or the extension so they get the emulated call
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
instance.load("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, 1U);
VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
// Compare against 'zeroed' out VkExternalMemoryProperties
ASSERT_EQ(VkExternalMemoryProperties{}, props.externalMemoryProperties);
ASSERT_TRUE(log.find("Emulating call in ICD"));
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("modify_api_version_layer")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DisableEnvVar")),
"modify_api_version_layer.json");
env.get_test_layer().set_alter_api_version(VK_API_VERSION_1_1);
{ // Now do the same as above but with a layer that updates the version to 1.1 on behalf of the application
InstWrapper instance(env.vulkan_functions);
instance.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
instance.CheckCreate();
DebugUtilsWrapper log{instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT};
CreateDebugUtilsMessenger(log);
PFN_vkGetPhysicalDeviceExternalBufferProperties GetPhysicalDeviceExternalBufferProperties =
instance.load("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, 1U);
VkPhysicalDeviceExternalBufferInfo info{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO};
VkExternalBufferProperties props{VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES};
GetPhysicalDeviceExternalBufferProperties(physical_device, &info, &props);
ASSERT_EQ(env.get_test_icd(0).physical_devices.back().external_memory_properties, props.externalMemoryProperties);
ASSERT_FALSE(log.find("Emulating call in ICD"));
}
}
// 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_2_EXPORT_ICD_GPDPA, icd != 1 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0));
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_C