diff --git a/src/yave_vulkan_instance.cpp b/src/yave_vulkan_instance.cpp index b89d9f0..3407bee 100644 --- a/src/yave_vulkan_instance.cpp +++ b/src/yave_vulkan_instance.cpp @@ -1,9 +1,13 @@ #include "yave_vulkan_instance.hpp" +#include #include namespace yave { -YaveVulkanInstance::YaveVulkanInstance() { createInstance(); } +YaveVulkanInstance::YaveVulkanInstance() { + createInstance(); + pickPhysicalDevice(); +} YaveVulkanInstance::~YaveVulkanInstance() { destroyInstance(); } void YaveVulkanInstance::createInstance() { @@ -76,4 +80,71 @@ bool YaveVulkanInstance::checkLayersValidSuppport( return true; } +// TODO: Create way to pick the most powerful and feature rich device +//(maybe use a suitability score rather than bool) +// Right now we're settling for the first device with queue family support +bool YaveVulkanInstance::isDeviceSuitable(VkPhysicalDevice device) { + QueueFamilyIndices indices = findQueueFamilies(device); + + return indices.isComplete(); +} + +void YaveVulkanInstance::pickPhysicalDevice() { + physicalDevice = VK_NULL_HANDLE; + + // Get number of vulken enabled devices on system + uint32_t deviceCount = 0; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + + // No point in running vulkan if it's not supported on any devices + if (deviceCount == 0) { + throw std::runtime_error("failed to find GPUs with Vulkan support!"); + } + + // Now we have the number of devices we can create a vector to store them for + // evaluation + std::vector devices(deviceCount); + vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + + // Use our suitability function to see if a device is suitable + for (const auto &device : devices) { + if (isDeviceSuitable(device)) { + physicalDevice = device; + break; + } + } + + // If we couldn't select a device throw an error + if (physicalDevice == VK_NULL_HANDLE) { + throw std::runtime_error("failed to find a suitable GPU!"); + } +} + +QueueFamilyIndices +YaveVulkanInstance::findQueueFamilies(VkPhysicalDevice device) { + // Get number of queues + QueueFamilyIndices indices; + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); + + // Put queues into vector + std::vector queueFamilies(queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, + queueFamilies.data()); + + // iterate over the devices ques and see if it has a graphics bit + int i = 0; + for (const auto &queueFamily : queueFamilies) { + if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { + indices.graphicsFamily = i; + } + // If we know we have support we don't need to look for anything more + if(indices.isComplete()){ + break; + } + i++; + } + return indices; +} + } // namespace yave diff --git a/src/yave_vulkan_instance.hpp b/src/yave_vulkan_instance.hpp index 8b93370..d945099 100644 --- a/src/yave_vulkan_instance.hpp +++ b/src/yave_vulkan_instance.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -9,13 +10,29 @@ #include namespace yave { + +struct QueueFamilyIndices { + std::optional graphicsFamily; + + bool isComplete() { return graphicsFamily.has_value(); } +}; + class YaveVulkanInstance { private: VkInstance instance; + VkPhysicalDevice physicalDevice; + + // Vulkan instance void createInstance(); void destroyInstance(); + // TODO: Move Physical device code to it's own class + // Physical device + void pickPhysicalDevice(); + bool isDeviceSuitable(VkPhysicalDevice device); + QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); + // Validation support bool checkLayersValidSuppport(VkInstanceCreateInfo &createInfo); const std::vector validationLayers = {