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

This commit is contained in:
Lillian Salehi 2024-10-05 19:59:15 -05:00
parent f161504410
commit 9a6a351e23
7 changed files with 64 additions and 9 deletions

View File

@ -1,16 +1,25 @@
#include "DeviceLibrary.h"
#include "debug/VulkanDebugLibs.h"
#include "global.h"
#include <cstdint>
#include <iostream>
#include <optional>
#include <ostream>
#include <stdexcept>
#include <vector>
#include <vulkan/vulkan_core.h>
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<uint32_t> 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<uint32_t>(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);
}

View File

@ -1,7 +1,9 @@
#pragma once
#include <vulkan/vulkan_core.h>
namespace AgnosiaEngine {
class DeviceLibrary {
public:
void pickPhysicalDevice(VkInstance& instance);
void createLogicalDevice(VkDevice& devicvee);
};
}

View File

@ -1,14 +1,13 @@
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <vulkan/vk_platform.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include "../global.h"
#include "VulkanDebugLibs.h"
using namespace AgnosiaEngine;
#include <vector>
#include <cstring>
#include <vulkan/vulkan_core.h>
@ -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<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
std::vector<const char*> 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;
}

View File

@ -1,3 +1,5 @@
#pragma once
#include <vector>
#include <vulkan/vulkan_core.h>
namespace AgnosiaEngine {

5
src/global.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "global.h"
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};

5
src/global.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <iostream>
#include <vector>
extern const std::vector<const char*> validationLayers;

View File

@ -1,5 +1,6 @@
#include <vector>
#include <vulkan/vulkan_core.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
@ -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);
}