From 9a6a351e2340cb9b7f7fd4d6b8b03fefacd38441 Mon Sep 17 00:00:00 2001 From: Lillian Salehi Date: Sat, 5 Oct 2024 19:59:15 -0500 Subject: [PATCH] Added Logical Device setup, currently there are a few errors thrown because we don't enable any extensions, but DO enable optional features, which rely on those extensions. It seems like vulkan can deal with these errors without crashing, but this will be addressed shortly regardless --- src/DeviceLibrary.cpp | 44 +++++++++++++++++++++++++++++++++-- src/DeviceLibrary.h | 2 ++ src/debug/VulkanDebugLibs.cpp | 7 ++---- src/debug/VulkanDebugLibs.h | 2 ++ src/global.cpp | 5 ++++ src/global.h | 5 ++++ src/main.cpp | 8 +++++-- 7 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 src/global.cpp create mode 100644 src/global.h diff --git a/src/DeviceLibrary.cpp b/src/DeviceLibrary.cpp index 13c72f5..8243cd2 100644 --- a/src/DeviceLibrary.cpp +++ b/src/DeviceLibrary.cpp @@ -1,16 +1,25 @@ #include "DeviceLibrary.h" +#include "debug/VulkanDebugLibs.h" +#include "global.h" + #include -#include #include #include #include -#include #include using namespace AgnosiaEngine; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkPhysicalDeviceProperties deviceProperties; VkPhysicalDeviceFeatures deviceFeatures; +VulkanDebugLibs debug; +VkQueue graphicsQueue; + +#ifdef DEBUG + const bool enableValidationLayers = true; +#else + const bool enableValidationLayers = false; +#endif struct QueueFamilyIndices { std::optional graphicsFamily; @@ -56,6 +65,7 @@ bool isDeviceSuitable(VkPhysicalDevice device) { // We need to find a device that supports graphical operations, or else we cant do much with it! This function just runs over all the queueFamilies and sees if there // is a queue family with the VK_QUEUE_GRAPHICS_BIT flipped! QueueFamilyIndices indices = findQueueFamilies(device); + return deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && deviceFeatures.multiViewport && deviceFeatures.geometryShader && indices.isComplete(); } @@ -84,4 +94,34 @@ void DeviceLibrary::pickPhysicalDevice(VkInstance& instance) { } } +void DeviceLibrary::createLogicalDevice(VkDevice& device) { + // Describe how many queues we want for a single family (1) here, right now we are solely interested in graphics capabilites, + // but Compute Shaders, transfer ops, decode and encode operations can also queued with setup! We also assign each queue a priority. + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + VkDeviceQueueCreateInfo queueCreateInfo{}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value(); + queueCreateInfo.queueCount = 1; + + float queuePriority = 1.0f; + queueCreateInfo.pQueuePriorities = &queuePriority; + + VkDeviceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.pQueueCreateInfos = &queueCreateInfo; + createInfo.queueCreateInfoCount = 1; + createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.enabledExtensionCount = 0; + + if(enableValidationLayers) { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + } else { + createInfo.enabledLayerCount = 0; + } + if(vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { + throw std::runtime_error("Failed to create logical device"); + } + vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); +} diff --git a/src/DeviceLibrary.h b/src/DeviceLibrary.h index 6364294..1992923 100644 --- a/src/DeviceLibrary.h +++ b/src/DeviceLibrary.h @@ -1,7 +1,9 @@ +#pragma once #include namespace AgnosiaEngine { class DeviceLibrary { public: void pickPhysicalDevice(VkInstance& instance); + void createLogicalDevice(VkDevice& devicvee); }; } diff --git a/src/debug/VulkanDebugLibs.cpp b/src/debug/VulkanDebugLibs.cpp index b092d56..243512f 100644 --- a/src/debug/VulkanDebugLibs.cpp +++ b/src/debug/VulkanDebugLibs.cpp @@ -1,14 +1,13 @@ #include -#include #include #include #define GLFW_INCLUDE_VULKAN #include +#include "../global.h" #include "VulkanDebugLibs.h" using namespace AgnosiaEngine; -#include #include #include @@ -21,9 +20,6 @@ using namespace AgnosiaEngine; // This is our messenger object! It handles passing along debug messages to the debug callback we will also set. VkDebugUtilsMessengerEXT debugMessenger; // This is the set of "layers" to hook into. Basically, layers are used to tell the messenger what data we want, its a filter. *validation* is the general blanket layer to cover incorrect usage. -const std::vector validationLayers = { - "VK_LAYER_KHRONOS_validation" -}; std::vector getRequiredExtensions() { // This gets a little weird, Vulkan is platform agnostic, so you need to figure out what extensions to interface with the current system are needed @@ -50,6 +46,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( // The VKAPI_CALL and VKAPI_ATTR ensure that the function has the right signature for vulkan to call it. The callback message can be anything from a diagnostic to error! // You can even sort by those diagnostics with their flags, since they are just integers, maybe TODO? std::cerr << "Validation layer: " << pCallbackData->pMessage << std::endl; + std::cout << "\n"; return VK_FALSE; } diff --git a/src/debug/VulkanDebugLibs.h b/src/debug/VulkanDebugLibs.h index 8cc7a34..195b5b0 100644 --- a/src/debug/VulkanDebugLibs.h +++ b/src/debug/VulkanDebugLibs.h @@ -1,3 +1,5 @@ +#pragma once +#include #include namespace AgnosiaEngine { diff --git a/src/global.cpp b/src/global.cpp new file mode 100644 index 0000000..b830e75 --- /dev/null +++ b/src/global.cpp @@ -0,0 +1,5 @@ +#include "global.h" + +const std::vector validationLayers = { + "VK_LAYER_KHRONOS_validation" +}; diff --git a/src/global.h b/src/global.h new file mode 100644 index 0000000..bee9eea --- /dev/null +++ b/src/global.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include + +extern const std::vector validationLayers; diff --git a/src/main.cpp b/src/main.cpp index 16745b6..67025f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include +#include #define GLFW_INCLUDE_VULKAN #include @@ -37,7 +38,8 @@ private: GLFWwindow* window; VkInstance instance; VulkanDebugLibs debug; - DeviceLibrary device; + DeviceLibrary deviceLibs; + VkDevice device; // Initialize GLFW Window. First, Initialize GLFW lib, disable resizing for // now, and create window. void initWindow() { @@ -52,7 +54,8 @@ private: void initVulkan() { createInstance(); debug.setupDebugMessenger(instance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DNDEBUG flag (as per the makefile) - device.pickPhysicalDevice(instance); + deviceLibs.pickPhysicalDevice(instance); + deviceLibs.createLogicalDevice(device); } void createInstance() { @@ -82,6 +85,7 @@ private: } void cleanup() { // Similar to the last handoff, destroy the debug util in a safe manner in the library! + vkDestroyDevice(device, nullptr); if(enableValidationLayers) { debug.DestroyDebugUtilsMessengerEXT(instance, nullptr); }