8

I've been messing around with Vulkan recently. In all of my experiments, when I select a gpu/vkDevice, I always just take the first one vulkan provides. I've looked at the documentation for vkDevice, and found that there is a lot of info, however I don't know how to decide what gpu is best for my program. I've considered using just max resolution, but it seems to me that there must be a better way.

Thanks :D

user2129189
  • 387
  • 3
  • 8
  • Does your device count return more than one device? –  Jul 01 '16 at 03:24
  • @MattJens No, so my issue doesn't affect my setup, but I want my code to be more portable. – user2129189 Jul 01 '16 at 03:35
  • 1
    Vulkan is severely lacking for this functionality right now, I still enumerate it and let the user choose in my options but I have two GPUs and only one shows up, even in a machine where I have two different brands of GPUs ( http://gamedev.stackexchange.com/q/121415/5665 ) might have to wait a little bit before Vulkan matures. –  Jul 01 '16 at 03:39
  • @MattJensJensen ah okay that makes sense. Thanks for the speedy reply! – user2129189 Jul 01 '16 at 03:44
  • 1
    My pleasure mate, when Vulkan is working on my platform I'll most likely post an update here of what I do to choose the default device by capabilities. –  Jul 01 '16 at 03:46

1 Answers1

9

There are two factors that I've found to be the simplest and easiest way to decide which of the available GPUs will be the most powerful for a game:

  1. Device Type (Discrete vs. Integrated vs. Other)
  2. Graphics Memory

Now of course for gaming more VRAM doesn't always mean better performance (a 980 Ti [6GB] usually outperforms a Titan X [12GB] in games) but in most cases the best GPU for your game will be a discrete GPU with the most available device local heap on a typical player's computer.

Now in Vulkan, it's fairly simple to check these properties by getting a list of physical devices, getting their device properties, getting their memory properties, and then getting their heap properties:

// ... assume Vulkan instance has been created successfully.
auto gpuCount = uint32_t{0};
vkEnumeratePhysicalDevices(instance, &gpuCount, nullptr);

auto devices = std::vector<VkPhysicalDevice>(gpuCount);
vkEnumeratePhysicalDevices(instance, &gpuCount, devices.data());

for (const auto& device : devices)
{
    auto props = VkPhysicalDeviceProperties{};
    vkGetPhysicalDeviceProperties(device, &props);

    // Determine the type of the physical device
    if (props.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
    {
        // You've got yourself a discrete GPU. (ideal)
    }
    else if (props.deviceType == VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
    {
        // You've got yourself an integrated GPU.
    }
    else
    {
        // I don't even...
    }

    // Determine the available device local memory.
    auto memoryProps = VkPhysicalDeviceMemoryProperies{};
    vkGetPhysicalDeviceMemoryProperties(device, &memoryProps);

    auto heapsPointer = memoryProps.memoryHeaps;
    auto heaps = std::vector<VkMemoryHeap>(heapsPointer, heapsPointer + memoryProps.memoryHeapCount);

    for (const auto& heap : heaps)
    {
        if (heap.flags & VkMemoryHeapFlagBits::VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
        {
            // Device local heap, should be size of total GPU VRAM.
            //heap.size will be the size of VRAM in bytes. (bigger is better)
        }

    }
}

Now, if you'll pardon the quick and dirty code; you could easily collect the available device local heaps of each discrete GPU and select the biggest one, I personally just select the first discrete GPU because it's a quite rare occurrence that someone with multiple discrete GPUs would have two very different performance level cards for gaming.

Update as of 7/23/2016: Nvidia's latest GeForce Driver 368.69 will actually expose multiple physical devices.

Up until now, this answer has only been theoretically functional as my multiple physical devices were not being exposed to Vulkan with the previous Nvidia drivers. Without needing to update the Vulkan API being utilized, the latest GeForce driver will now iterate and expose and utilize everything that the multiple physical devices can offer. I can confirm that this code works as expected now.

  • 1
    of course after eliminating the devices that don't support the capabilities you need. – ratchet freak Jul 01 '16 at 13:04
  • It's very unlikely that Vulkan will find a discrete GPU that supports Vulkan 1.0+ that doesn't have the capabilities that you'll need for games, if you fail to create a graphics queue down the line after finding a discrete GPU that's an entirely different set of issues. What other criterion would you use to rule out a GPU at this level? –  Jul 01 '16 at 13:12
  • tesselation support, sparse binding support, dynamic array indexing. Or Where the limits are not what you need concerning samplers in shaders for example. – ratchet freak Jul 01 '16 at 13:20
  • 1
    Fair enough, but it's unlikely that an integrated GPU would support those features over a discrete GPU. Those features aren't necessary for displaying a menu UI where the user can select which GPU to use for rendering in the rare case that they have a GTX 650 plugged in next to a GTX 980 and somehow the GTX 650 is the default card Vulkan picks. It is also worth noting that tessellation support, sparse binding support, dynamic array indexing are not usually hard features that you would say "Oh, this GPU doesn't support these features... it looks like they can't play this game." –  Jul 01 '16 at 13:25