Boy this is messy, but for the love of god let surface config from the vulkan tutorial be over.

This commit is contained in:
Warwick 2024-05-02 15:54:48 +01:00
parent 11887dae98
commit ce1d58b086
5 changed files with 60 additions and 34 deletions

View file

@ -1,12 +1,10 @@
#include "application.hpp" #include "application.hpp"
#include "yave_vulkan_instance.hpp" #include "yave_vulkan_instance.hpp"
#include "yave_vulkan_surface.hpp"
namespace yave { namespace yave {
void Application::run() { void Application::run() {
YaveVulkanInstance VI = YaveVulkanInstance(); YaveVulkanInstance VI = YaveVulkanInstance(&yaveWindow);
YaveVulkanSurface VS = YaveVulkanSurface(VI, yaveWindow);
while (!yaveWindow.shouldClose()) { while (!yaveWindow.shouldClose()) {
glfwPollEvents(); glfwPollEvents();

View file

@ -1,16 +1,19 @@
#include "yave_vulkan_instance.hpp" #include "yave_vulkan_instance.hpp"
#include <cstdint> #include <cstdint>
#include <set>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
namespace yave { namespace yave {
YaveVulkanInstance::YaveVulkanInstance() { YaveVulkanInstance::YaveVulkanInstance(YaveWindow *window) : window(window) {
createInstance(); createInstance();
surface = new YaveVulkanSurface(*this, window);
pickPhysicalDevice(); pickPhysicalDevice();
createLogicalDevice(); createLogicalDevice();
} }
YaveVulkanInstance::~YaveVulkanInstance() { YaveVulkanInstance::~YaveVulkanInstance() {
destroyLogicalDevice(); destroyLogicalDevice();
delete surface;
destroyInstance(); destroyInstance();
} }
@ -142,41 +145,55 @@ YaveVulkanInstance::findQueueFamilies(VkPhysicalDevice device) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
indices.graphicsFamily = i; indices.graphicsFamily = i;
} }
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, *surface->getVkSurface(),
&presentSupport);
if (presentSupport) {
indices.presentFamily = i;
}
// If we know we have support we don't need to look for anything more // If we know we have support we don't need to look for anything more
if (indices.isComplete()) { if (indices.isComplete()) {
break; break;
} }
i++; i++;
} }
return indices; return indices;
} }
void YaveVulkanInstance::createLogicalDevice() { void YaveVulkanInstance::createLogicalDevice() {
QueueFamilyIndices indices = findQueueFamilies(physicalDevice); QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
// Only need a single queue as we can feed it with multiple threads and std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
// trigger it from the main thread to start off with. std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(),
indices.presentFamily.value()};
float queuePriority = 1.0f;
for (uint32_t queueFamily : uniqueQueueFamilies) {
VkDeviceQueueCreateInfo queueCreateInfo{}; VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value(); queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1; queueCreateInfo.queueCount = 1;
// Since we only have one queue it has all the priority.
float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority; queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.push_back(queueCreateInfo);
}
// TODO: set up device with interesting features as we use them
VkPhysicalDeviceFeatures deviceFeatures{}; VkPhysicalDeviceFeatures deviceFeatures{};
// Create logical device.
VkDeviceCreateInfo createInfo{}; VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 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.pEnabledFeatures = &deviceFeatures;
// TODO: Require specific features when we need some
// Device specific create information
createInfo.enabledExtensionCount = 0; createInfo.enabledExtensionCount = 0;
if (enableValidationLayers) { if (enableValidationLayers) {
createInfo.enabledLayerCount = createInfo.enabledLayerCount =
static_cast<uint32_t>(validationLayers.size()); static_cast<uint32_t>(validationLayers.size());
@ -185,14 +202,13 @@ void YaveVulkanInstance::createLogicalDevice() {
createInfo.enabledLayerCount = 0; createInfo.enabledLayerCount = 0;
} }
// Create logical device
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) !=
VK_SUCCESS) { VK_SUCCESS) {
throw std::runtime_error("failed to create logical device!"); throw std::runtime_error("failed to create logical device!");
} }
// Whilst we're here we might as well set up our queue
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
} }
void YaveVulkanInstance::destroyLogicalDevice() { void YaveVulkanInstance::destroyLogicalDevice() {

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "yave_vulkan_surface.hpp"
#include "yave_window.hpp"
#include <cstring> #include <cstring>
#include <optional> #include <optional>
#include <stdexcept> #include <stdexcept>
@ -13,8 +15,11 @@ namespace yave {
struct QueueFamilyIndices { struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily; std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool isComplete() { return graphicsFamily.has_value(); } bool isComplete() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
}; };
class YaveVulkanInstance { class YaveVulkanInstance {
@ -24,6 +29,9 @@ private:
VkPhysicalDevice physicalDevice; VkPhysicalDevice physicalDevice;
VkDevice device; VkDevice device;
VkQueue graphicsQueue; VkQueue graphicsQueue;
YaveVulkanSurface *surface;
YaveWindow *window;
VkQueue presentQueue;
// Vulkan instance // Vulkan instance
void createInstance(); void createInstance();
@ -56,8 +64,8 @@ public:
YaveVulkanInstance(const YaveVulkanInstance &) = delete; YaveVulkanInstance(const YaveVulkanInstance &) = delete;
YaveVulkanInstance &operator=(const YaveVulkanInstance &) = delete; YaveVulkanInstance &operator=(const YaveVulkanInstance &) = delete;
VkInstance *getVkInstance(){return &instance;} VkInstance *getVkInstance() { return &instance; }
YaveVulkanInstance(); YaveVulkanInstance(YaveWindow *window);
~YaveVulkanInstance(); ~YaveVulkanInstance();
}; };
} // namespace yave } // namespace yave

View file

@ -7,16 +7,18 @@
namespace yave { namespace yave {
YaveVulkanSurface::YaveVulkanSurface(YaveVulkanInstance &yaveVulkanInstance, YaveVulkanSurface::YaveVulkanSurface(YaveVulkanInstance &yaveVulkanInstance,
YaveWindow &window) { YaveWindow *window)
this->instance = yaveVulkanInstance.getVkInstance(); : instance(yaveVulkanInstance) {
if (glfwCreateWindowSurface(*instance, window.getGLFWWindow(), nullptr, if (glfwCreateWindowSurface(*instance.getVkInstance(),
&surface)) { window->getGLFWWindow(), nullptr, &surface)) {
throw std::runtime_error("failed to create window surface!"); throw std::runtime_error("failed to create window surface!");
} }
} }
VkSurfaceKHR *YaveVulkanSurface::getVkSurface() { return &this->surface; }
YaveVulkanSurface::~YaveVulkanSurface() { YaveVulkanSurface::~YaveVulkanSurface() {
vkDestroySurfaceKHR(*instance, surface, nullptr); vkDestroySurfaceKHR(*instance.getVkInstance(), surface, nullptr);
} }
} // namespace yave } // namespace yave

View file

@ -1,26 +1,28 @@
#pragma once #pragma once
#include "yave_vulkan_instance.hpp"
#include "yave_window.hpp" #include "yave_window.hpp"
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan_core.h>
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
namespace yave { namespace yave {
class YaveVulkanInstance;
class YaveVulkanSurface { class YaveVulkanSurface {
private: private:
// Keep reference to instance this surface is attached to // Keep reference to instance this surface is attached to
VkInstance *instance; YaveVulkanInstance &instance;
VkSurfaceKHR surface; VkSurfaceKHR surface;
public: public:
YaveVulkanSurface(YaveVulkanInstance &yaveVulkanInstance, YaveWindow &window); YaveVulkanSurface(YaveVulkanInstance &yaveVulkanInstance, YaveWindow *window);
~YaveVulkanSurface(); ~YaveVulkanSurface();
//
VkSurfaceKHR *getVkSurface();
// Delete Copy constructors // Delete Copy constructors
// This class should match one to one with vulkan instances // This class should match one to one with vulkan instances
YaveVulkanSurface(const YaveVulkanSurface &) = delete; YaveVulkanSurface(const YaveVulkanSurface &) = delete;