samples/test-harness/src/Vulkan.cpp
CreateDeviceInternal function does not check for device extensions support, but rather picks first device with graphics queue support.
This behavior results in program crash when executed on systems with multiple gpus, possibly one of them integrated to the CPU (like laptops for example).
/**
* Create the Vulkan device and queue.
*/
bool CreateDeviceInternal(Globals& vk, Configs::Config& config)
{
// Get the number of physical graphics devices
uint32_t physicalDeviceCount = 0;
VKCHECK(vkEnumeratePhysicalDevices(vk.instance, &physicalDeviceCount, nullptr));
if (physicalDeviceCount == 0) return false;
// Get the list of physical devices
std::vector<VkPhysicalDevice> devices(physicalDeviceCount);
VKCHECK(vkEnumeratePhysicalDevices(vk.instance, &physicalDeviceCount, devices.data()));
// Find a physical device that supports graphics queues
if (!FindPhysicalDeviceWithGraphicsQueue(devices, &vk.physicalDevice, &vk.queueFamilyIndex)) return false;
....
}
Possible fix to this would be to implement extensions check support to the FindPhysicalDeviceWithGraphicsQueue
Like this:
bool CheckDeviceExtensions(VkPhysicalDevice device,
const std::vector<const char*>& requiredExtensions)
{
uint32_t count;
vkEnumerateDeviceExtensionProperties(device, nullptr, &count, nullptr);
std::vector<VkExtensionProperties> available(count);
vkEnumerateDeviceExtensionProperties(device, nullptr, &count, available.data());
std::unordered_set<std::string> required(requiredExtensions.begin(), requiredExtensions.end());
for (const auto& ext : available)
required.erase(ext.extensionName);
return required.empty();
}
/**
* Search a list of physical devices for one that supports a graphics queue.
*/
bool FindPhysicalDeviceWithGraphicsQueueAndExtensions(const std::vector<VkPhysicalDevice>& physicalDevices, const std::vector<const char*>& requiredExtensions, VkPhysicalDevice* device, int* graphicsQueueIndex)
{
for (uint32_t deviceIndex = 0; deviceIndex < static_cast<uint32_t>(physicalDevices.size()); deviceIndex++)
{
// Get the physical device
const VkPhysicalDevice physicalDevice = physicalDevices[deviceIndex];
// Get the number of extension properties
if (!CheckDeviceExtensions(physicalDevice, requiredExtensions)) continue;
// Get the number of properties
uint32_t queueFamilyPropertyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertyCount, nullptr);
if (queueFamilyPropertyCount == 0) continue;
// Get a list of the queue properties
std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyPropertyCount);
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertyCount, queueFamilyProperties.data());
// Inspect the list of properties to see if the physical device supports graphics queues
for (uint32_t propertyIndex = 0; propertyIndex < static_cast<uint32_t>(queueFamilyProperties.size()); propertyIndex++)
{
const VkQueueFamilyProperties props = queueFamilyProperties[propertyIndex];
if (props.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
if (device) *device = physicalDevice;
if (graphicsQueueIndex) *graphicsQueueIndex = propertyIndex;
return true;
}
}
}
return false;
}
Although it is also not perfect, since here the code doesn't check for extension features support.
samples/test-harness/src/Vulkan.cpp
CreateDeviceInternalfunction does not check for device extensions support, but rather picks first device with graphics queue support.This behavior results in program crash when executed on systems with multiple gpus, possibly one of them integrated to the CPU (like laptops for example).
Possible fix to this would be to implement extensions check support to the
FindPhysicalDeviceWithGraphicsQueueLike this:
Although it is also not perfect, since here the code doesn't check for extension features support.