device suitability is in a better place now

This commit is contained in:
Ben Kyd
2023-11-04 18:58:58 +00:00
parent cf1c6be4cb
commit c4f65d6599
9 changed files with 1298 additions and 157 deletions

View File

@@ -2,13 +2,15 @@
#include "gui/style.hpp"
#include <version.hpp>
#include <graphics.hpp>
#include <version.hpp>
#include "yolo/yolo.hpp"
#include <optional>
#include <set>
#include <vector>
#include <vulkan/vulkan_core.h>
namespace inferno::graphics {
@@ -17,9 +19,6 @@ static KeyCallback UserKeyCallback = nullptr;
static int Width, Height;
static GLFWwindow* Window;
static VkInstance VulkanInstance;
static VkPhysicalDevice VulkanPhysicalDevice = VK_NULL_HANDLE;
void glfwKeyCallback(GLFWwindow* window, int key, int scancode,
int action, int mods)
{
@@ -33,40 +32,6 @@ void glfwErrorCallback(int error, const char* description)
yolo::error("[GLFW {}] {}", error, description);
}
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
bool isComplete() {
return graphicsFamily.has_value();
}
};
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device)
{
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
int i = 0;
for (const auto& queueFamily : queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
indices.graphicsFamily = i;
}
if (indices.isComplete()) {
break;
}
i++;
}
return indices;
}
void setupGLFW(std::string title)
{
glfwSetErrorCallback(glfwErrorCallback);
@@ -84,6 +49,11 @@ void setupGLFW(std::string title)
if (Window == NULL)
throw std::runtime_error("Could not create window");
if (!glfwVulkanSupported()) {
yolo::error("Vulkan not supported");
exit(1);
}
// Vulkan Init
VkApplicationInfo appInfo {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -99,10 +69,13 @@ void setupGLFW(std::string title)
uint32_t glfwExtCount = 0;
const char** exts = glfwGetRequiredInstanceExtensions(&ext);
// add VK_KHR_xcb_surface to the list of extensions
// TODO: This is a massive fuck off hack - SOLVE IT!!!!
exts[glfwExtCount++] = "VK_KHR_xcb_surface";
instInfo.enabledExtensionCount = glfwExtCount;
instInfo.ppEnabledExtensionNames = exts;
instInfo.enabledLayerCount = 0;
yolo::info("GLFW requested {} extensions: {}", glfwExtCount, exts);
yolo::info("GLFW requested {} extensions: {}", glfwExtCount, exts[0]);
if (vkCreateInstance(&instInfo, nullptr, &VulkanInstance) != VK_SUCCESS) {
yolo::error("Could not create Vulkan instance");
@@ -120,14 +93,45 @@ void setupGLFW(std::string title)
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(VulkanInstance, &deviceCount, devices.data());
// TODO: We need to do device suitability in a much better way
const std::vector<const char*> deviceExtensions {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
for (const auto& device : devices) {
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
yolo::info("Found Vulkan device: {}", deviceProperties.deviceName);
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
&& deviceFeatures.geometryShader) {
const auto& checkDevExtensions = [&]() -> bool {
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
for (const auto& extension : availableExtensions) {
requiredExtensions.erase(extension.extensionName);
}
return requiredExtensions.empty();
};
const auto& isDeviceSuitable
= [&]() -> bool {
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
yolo::info("Found Vulkan device: {}", deviceProperties.deviceName);
bool features = deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && deviceFeatures.geometryShader;
QueueFamilyIndices indices = window_get_queue_families(device);
bool extensions = checkDevExtensions();
return indices.isComplete() && extensions && features;
};
if (isDeviceSuitable()) {
VulkanPhysicalDevice = device;
break;
}
@@ -139,19 +143,25 @@ void setupGLFW(std::string title)
}
// Logical Device
QueueFamilyIndices indices = findQueueFamilies(VulkanPhysicalDevice);
VkDeviceQueueCreateInfo queueCreateInfo {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
queueCreateInfo.queueCount = 1;
QueueFamilyIndices indices = window_get_queue_families(VulkanPhysicalDevice);
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;
for (uint32_t queueFamily : uniqueQueueFamilies) {
VkDeviceQueueCreateInfo queueCreateInfo {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.push_back(queueCreateInfo);
}
VkPhysicalDeviceFeatures deviceFeatures {};
VkDeviceCreateInfo createInfo {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = 0;
createInfo.enabledLayerCount = 0;
@@ -161,9 +171,18 @@ void setupGLFW(std::string title)
exit(1);
}
vkGetDeviceQueue(VulkanDevice, indices.graphicsFamily.value(), 0, &VulkanPresentQueue);
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(VulkanPhysicalDevice, &deviceProperties);
yolo::info("Vulkan running on ", deviceProperties.deviceName);
// "Surface" creation
VkResult result = glfwCreateWindowSurface(VulkanInstance, Window, nullptr, &VulkanSurface);
if (result != VK_SUCCESS) {
yolo::error("Could not create Vulkan surface (code: {})", result);
exit(1);
}
}
void setupImGui()
@@ -246,6 +265,8 @@ void window_create(std::string title, int width, int height)
void window_cleanup()
{
vkDestroySurfaceKHR(VulkanInstance, VulkanSurface, nullptr);
vkDestroyInstance(VulkanInstance, nullptr);
vkDestroyDevice(VulkanDevice, nullptr);
shutdownGLFW();
}
@@ -268,6 +289,41 @@ glm::vec2 window_get_size() { return { Width, Height }; }
void window_get_pos(int& x, int& y) { glfwGetWindowPos(Window, &x, &y); }
// VULKAN SPECIFIC
QueueFamilyIndices window_get_queue_families(VkPhysicalDevice device)
{
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
int i = 0;
for (const auto& queueFamily : queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
indices.graphicsFamily = i;
}
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, VulkanSurface, &presentSupport);
if (presentSupport) {
indices.presentFamily = i;
}
if (indices.isComplete()) {
break;
}
i++;
}
return indices;
}
// END VULKAN SPECIFIC
GLFWwindow* window_get_glfw_window() { return Window; }
void window_set_mode(WINDOW_MODE mode)