Added physical device picker

This commit is contained in:
Warwick 2023-12-03 12:21:57 +00:00
parent 6ee062cca6
commit e5f420a238
2 changed files with 89 additions and 1 deletions

View file

@ -1,9 +1,13 @@
#include "yave_vulkan_instance.hpp"
#include <cstdint>
#include <vulkan/vulkan_core.h>
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<VkPhysicalDevice> 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<VkQueueFamilyProperties> 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

View file

@ -1,6 +1,7 @@
#pragma once
#include <cstring>
#include <optional>
#include <stdexcept>
#include <vector>
#include <vulkan/vulkan.h>
@ -9,13 +10,29 @@
#include <GLFW/glfw3.h>
namespace yave {
struct QueueFamilyIndices {
std::optional<uint32_t> 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<const char *> validationLayers = {