diff --git a/src/HelloTriangleApplication.cpp b/src/HelloTriangleApplication.cpp index 2c1ab60..ff20abc 100644 --- a/src/HelloTriangleApplication.cpp +++ b/src/HelloTriangleApplication.cpp @@ -7,21 +7,14 @@ #include #include #include -#include -#include #define GLFW_INCLUDE_VULKAN #include -#include "debugLayers.h" #include "queues.h" #include "util.h" -const std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, -}; - VkShaderModule HelloTriangleApplication::createShaderModule(const std::vector &code) { VkShaderModuleCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; @@ -29,148 +22,24 @@ VkShaderModule HelloTriangleApplication::createShaderModule(const std::vector(code.data()); VkShaderModule shaderModule; - if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { + if (vkCreateShaderModule(myVkInstance->device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { throw std::runtime_error("Failed to create shader module"); } return shaderModule; } -bool isSuitableDevice(VkPhysicalDevice device, VkSurfaceKHR surface) { - VkPhysicalDeviceProperties deviceProperties; - VkPhysicalDeviceFeatures features; - QueueFamilyIndices indices; - - vkGetPhysicalDeviceProperties(device, &deviceProperties); - vkGetPhysicalDeviceFeatures(device, &features); - indices = findQueueFamilies(device, surface); - - bool extensionSupport = checkDeviceExtensionSupport(device, deviceExtensions); - bool swapChainAdequate = false; - if (extensionSupport) { - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, surface); - swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); - } - - return deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && - features.geometryShader && - indices.isComplete() && - extensionSupport && - swapChainAdequate; -} - void HelloTriangleApplication::run() { - initWindow(); + this->myVkInstance = new MyVkInstance(); + this->myVkInstance->init(); initVulkan(); mainLoop(); cleanup(); -} - -void HelloTriangleApplication::initWindow() { - glfwInit(); - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); - - window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); -} - -void HelloTriangleApplication::createInstance() { -#ifdef WITH_VALIDATION_LAYERS - if (!checkValidationLayerSupport()) { - throw std::runtime_error("validation layer support required"); - } -#endif - VkApplicationInfo appInfo{}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "Hello Triangle"; - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.pEngineName = "No Engine"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_0; - - VkInstanceCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; - - auto extensions = getRequiredExtensions(); - createInfo.enabledExtensionCount = static_cast(extensions.size()); - createInfo.ppEnabledExtensionNames = extensions.data(); - - -#ifdef WITH_VALIDATION_LAYERS - createInfo.enabledLayerCount = static_cast(validationLayers.size()); - createInfo.ppEnabledLayerNames = validationLayers.data(); -#else - createInfo.enabledLayerCount = 0; - createInfo.ppEnabledLayerNames = nullptr; -#endif - - if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { - throw std::runtime_error("Failed to create instance!"); - } -} - -void HelloTriangleApplication::createSurface() { - if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) { - throw std::runtime_error("Failed to create surface"); - } -} - -void HelloTriangleApplication::pickPhysicalDevice() { - uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); - if (deviceCount == 0) { - throw std::runtime_error("No devices available"); - } - std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); - for (const auto &device: devices) { - if (isSuitableDevice(device, surface)) { - physicalDevice = device; - break; - } - } - if (physicalDevice == VK_NULL_HANDLE) { - throw std::runtime_error("No suitable device found"); - } -} - -void HelloTriangleApplication::createLogicalDevice() { - QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface); - - std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()}; - float queuePriority = 1.0f; - 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 = queueCreateInfos.data(); - createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); - createInfo.pEnabledFeatures = &deviceFeatures; - createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); - createInfo.ppEnabledExtensionNames = deviceExtensions.data(); - 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); - vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); + this->myVkInstance->cleanup(); } void HelloTriangleApplication::createSwapChain() { - QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; - SwapChainSupportDetails swapChainSupportDetails = querySwapChainSupport(physicalDevice, surface); + uint32_t queueFamilyIndices[] = {myVkInstance->indices.graphicsFamily.value(), myVkInstance->indices.presentFamily.value()}; + SwapChainSupportDetails swapChainSupportDetails = querySwapChainSupport(myVkInstance->physicalDevice, myVkInstance->surface); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupportDetails.formats); VkPresentModeKHR presentMode = chooseSwapChainPresentMode(swapChainSupportDetails.presentModes); @@ -182,14 +51,14 @@ void HelloTriangleApplication::createSwapChain() { } VkSwapchainCreateInfoKHR createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = surface; + createInfo.surface = myVkInstance->surface; createInfo.minImageCount = imageCount; createInfo.imageFormat = surfaceFormat.format; createInfo.imageColorSpace = surfaceFormat.colorSpace; createInfo.imageExtent = extent; createInfo.imageArrayLayers = 1; createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - if (indices.graphicsFamily != indices.presentFamily) { + if (myVkInstance->indices.graphicsFamily != myVkInstance->indices.presentFamily) { createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; createInfo.queueFamilyIndexCount = 2; createInfo.pQueueFamilyIndices = queueFamilyIndices; @@ -204,12 +73,12 @@ void HelloTriangleApplication::createSwapChain() { createInfo.clipped = VK_TRUE; createInfo.oldSwapchain = VK_NULL_HANDLE; - if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) { + if (vkCreateSwapchainKHR(myVkInstance->device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) { throw std::runtime_error("Failed to create swapChain"); } - vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr); + vkGetSwapchainImagesKHR(myVkInstance->device, swapChain, &imageCount, nullptr); swapChainImages.resize(imageCount); - vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data()); + vkGetSwapchainImagesKHR(myVkInstance->device, swapChain, &imageCount, swapChainImages.data()); swapChainImageFormat = surfaceFormat.format; swapChainExtent = extent; } @@ -232,7 +101,7 @@ void HelloTriangleApplication::createImageViews() { createInfo.subresourceRange.baseArrayLayer = 0; createInfo.subresourceRange.layerCount = 1; - if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) { + if (vkCreateImageView(myVkInstance->device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) { throw std::runtime_error("Failed to create image view"); } } @@ -276,7 +145,7 @@ void HelloTriangleApplication::createRenderPass() { .pDependencies = &dependency, }; - if (vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &renderPass) != VK_SUCCESS) { + if (vkCreateRenderPass(myVkInstance->device, &renderPassCreateInfo, nullptr, &renderPass) != VK_SUCCESS) { throw std::runtime_error("Failed to create render pass"); } } @@ -414,7 +283,7 @@ void HelloTriangleApplication::createGraphicsPipeline() { .pPushConstantRanges = nullptr, }; - if (vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { + if (vkCreatePipelineLayout(myVkInstance->device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { throw std::runtime_error("failed to create pipeline layout"); } @@ -437,12 +306,12 @@ void HelloTriangleApplication::createGraphicsPipeline() { .basePipelineIndex = -1, }; - if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { + if (vkCreateGraphicsPipelines(myVkInstance->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { throw std::runtime_error("Failed to create graphics pipeline"); } - vkDestroyShaderModule(device, fragShaderModule, nullptr); - vkDestroyShaderModule(device, vertShaderModule, nullptr); + vkDestroyShaderModule(myVkInstance->device, fragShaderModule, nullptr); + vkDestroyShaderModule(myVkInstance->device, vertShaderModule, nullptr); } void HelloTriangleApplication::createFrameBuffers() { @@ -460,22 +329,20 @@ void HelloTriangleApplication::createFrameBuffers() { .height = swapChainExtent.height, .layers = 1 }; - if (vkCreateFramebuffer(device, &framebufferCreateInfo, nullptr, &swapChainFrameBuffers[i]) != VK_SUCCESS) { + if (vkCreateFramebuffer(myVkInstance->device, &framebufferCreateInfo, nullptr, &swapChainFrameBuffers[i]) != VK_SUCCESS) { throw std::runtime_error("Failed to create frame buffer"); } } } void HelloTriangleApplication::createCommandPool() { - QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice, surface); - VkCommandPoolCreateInfo poolInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .flags = 0, - .queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(), + .queueFamilyIndex = myVkInstance->indices.graphicsFamily.value(), }; - if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { + if (vkCreateCommandPool(myVkInstance->device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { throw std::runtime_error("Failed to create command pool"); } } @@ -490,7 +357,7 @@ void HelloTriangleApplication::createCommandBuffers() { .commandBufferCount = (uint32_t) commandBuffers.size(), }; - if (vkAllocateCommandBuffers(device, &allocateInfo, commandBuffers.data()) != VK_SUCCESS) { + if (vkAllocateCommandBuffers(myVkInstance->device, &allocateInfo, commandBuffers.data()) != VK_SUCCESS) { throw std::runtime_error("Failed to allocate command buffers"); } @@ -538,22 +405,15 @@ void HelloTriangleApplication::createSyncObjects() { }; for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - if (vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS || - vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i])) { + if (vkCreateSemaphore(myVkInstance->device, &semaphoreCreateInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS || + vkCreateSemaphore(myVkInstance->device, &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS || + vkCreateFence(myVkInstance->device, &fenceInfo, nullptr, &inFlightFences[i])) { throw std::runtime_error("failed to create semaphore"); } } } void HelloTriangleApplication::initVulkan() { - createInstance(); -#ifdef WITH_VALIDATION_LAYERS - setupDebugMessenger(instance, &debugMessenger); -#endif - createSurface(); - pickPhysicalDevice(); - createLogicalDevice(); createSwapChain(); createImageViews(); createRenderPass(); @@ -565,20 +425,20 @@ void HelloTriangleApplication::initVulkan() { } void HelloTriangleApplication::mainLoop() { - while (!glfwWindowShouldClose(window)) { + while (!glfwWindowShouldClose(myVkInstance->window)) { glfwPollEvents(); drawFrame(); } - vkDeviceWaitIdle(device); + vkDeviceWaitIdle(myVkInstance->device); } void HelloTriangleApplication::drawFrame() { - vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + vkWaitForFences(myVkInstance->device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); uint32_t imageIndex; - vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + vkAcquireNextImageKHR(myVkInstance->device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); if (imagesInFlight[currentFrame] != VK_NULL_HANDLE) { - vkWaitForFences(device, 1, &imagesInFlight[currentFrame], VK_TRUE, UINT64_MAX); + vkWaitForFences(myVkInstance->device, 1, &imagesInFlight[currentFrame], VK_TRUE, UINT64_MAX); } imagesInFlight[currentFrame] = inFlightFences[currentFrame]; @@ -596,9 +456,9 @@ void HelloTriangleApplication::drawFrame() { .pSignalSemaphores = signalSemaphores, }; - vkResetFences(device, 1, &inFlightFences[currentFrame]); + vkResetFences(myVkInstance->device, 1, &inFlightFences[currentFrame]); - if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) { + if (vkQueueSubmit(myVkInstance->graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) { throw std::runtime_error("Failed to submit draw command"); } @@ -613,7 +473,7 @@ void HelloTriangleApplication::drawFrame() { .pResults = nullptr, }; - vkQueuePresentKHR(presentQueue, &presentInfo); + vkQueuePresentKHR(myVkInstance->presentQueue, &presentInfo); // vkQueueWaitIdle(presentQueue); currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; @@ -621,41 +481,19 @@ void HelloTriangleApplication::drawFrame() { void HelloTriangleApplication::cleanup() { for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { - vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); - vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); - vkDestroyFence(device, inFlightFences[i], nullptr); + vkDestroySemaphore(myVkInstance->device, renderFinishedSemaphores[i], nullptr); + vkDestroySemaphore(myVkInstance->device, imageAvailableSemaphores[i], nullptr); + vkDestroyFence(myVkInstance->device, inFlightFences[i], nullptr); } - vkDestroyCommandPool(device, commandPool, nullptr); + vkDestroyCommandPool(myVkInstance->device, commandPool, nullptr); for (auto frameBuffer : swapChainFrameBuffers) { - vkDestroyFramebuffer(device, frameBuffer, nullptr); + vkDestroyFramebuffer(myVkInstance->device, frameBuffer, nullptr); } - vkDestroyPipeline(device, graphicsPipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyRenderPass(device, renderPass, nullptr); + vkDestroyPipeline(myVkInstance->device, graphicsPipeline, nullptr); + vkDestroyPipelineLayout(myVkInstance->device, pipelineLayout, nullptr); + vkDestroyRenderPass(myVkInstance->device, renderPass, nullptr); for (auto imageView : swapChainImageViews) { - vkDestroyImageView(device, imageView, nullptr); + vkDestroyImageView(myVkInstance->device, imageView, nullptr); } - vkDestroySwapchainKHR(device, swapChain, nullptr); - vkDestroyDevice(device, nullptr); - vkDestroySurfaceKHR(instance, surface, nullptr); -#ifdef WITH_VALIDATION_LAYERS - DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); -#endif - vkDestroyInstance(instance, nullptr); - glfwDestroyWindow(window); - glfwTerminate(); -} - -std::vector HelloTriangleApplication::getRequiredExtensions() { - uint32_t glfwExtensionCount; - const char **glfwExtensions; - glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - - std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); - -#ifdef WITH_VALIDATION_LAYERS - extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); -#endif - - return extensions; + vkDestroySwapchainKHR(myVkInstance->device, swapChain, nullptr); } diff --git a/src/HelloTriangleApplication.h b/src/HelloTriangleApplication.h index 1bfe2b6..31da1e3 100644 --- a/src/HelloTriangleApplication.h +++ b/src/HelloTriangleApplication.h @@ -5,6 +5,8 @@ #ifndef VULKANTEST_HELLOTRIANGLEAPPLICATION_H #define VULKANTEST_HELLOTRIANGLEAPPLICATION_H +#include "MyVkInstance.h" + #include #define GLFW_INCLUDE_VULKAN @@ -20,14 +22,7 @@ public: void run(); private: - GLFWwindow* window; - VkInstance instance; - VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; - VkDevice device; - VkQueue graphicsQueue; - VkQueue presentQueue; - VkSurfaceKHR surface; - VkDebugUtilsMessengerEXT debugMessenger; + MyVkInstance *myVkInstance; VkSwapchainKHR swapChain; std::vector swapChainImages; std::vector swapChainImageViews; @@ -47,13 +42,7 @@ private: int currentFrame = 0; - // window creation - void initWindow(); - // Vulkan initialisation - void createInstance(); - void pickPhysicalDevice(); - void createLogicalDevice(); void createSurface(); void createSwapChain(); void createImageViews(); diff --git a/src/MyVkInstance.cpp b/src/MyVkInstance.cpp new file mode 100644 index 0000000..84e5e33 --- /dev/null +++ b/src/MyVkInstance.cpp @@ -0,0 +1,199 @@ +// +// Created by rick on 30-05-20. +// + +#include "MyVkInstance.h" +#include "debugLayers.h" +#include "queues.h" + +#include +#include +#include + +const int DEFAULT_WIDTH = 600; +const int DEFAULT_HEIGHT = 300; +const char* DEFAULT_TITLE = "Vulkan"; + +const char* deviceExtensions[] = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, +}; + +std::vector getRequiredExtensions() { + uint32_t glfwExtensionCount; + const char **glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + + std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + +#ifdef WITH_VALIDATION_LAYERS + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); +#endif + + return extensions; +} + +bool isSuitableDevice(VkPhysicalDevice device, VkSurfaceKHR surface) { + VkPhysicalDeviceProperties deviceProperties; + VkPhysicalDeviceFeatures features; + QueueFamilyIndices indices; + + vkGetPhysicalDeviceProperties(device, &deviceProperties); + vkGetPhysicalDeviceFeatures(device, &features); + indices = findQueueFamilies(device, surface); + + bool extensionSupport = checkDeviceExtensionSupport(device, deviceExtensions, sizeof(deviceExtensions) / sizeof(void*)); + bool swapChainAdequate = false; + if (extensionSupport) { + SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device, surface); + swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); + } + + return deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && + features.geometryShader && + indices.isComplete() && + extensionSupport && + swapChainAdequate; +} + + +MyVkInstance::MyVkInstance(){ + new (this) MyVkInstance(DEFAULT_WIDTH, DEFAULT_HEIGHT, const_cast(DEFAULT_TITLE)); +} + +MyVkInstance::MyVkInstance(int width, int height, char* &title) { + this->width = width; + this->height = height; + this->title = title; +} + +void MyVkInstance::init() { + this->initWindow(); + this->initVulkan(); +} + +void MyVkInstance::initWindow() { + glfwInit(); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + + window = glfwCreateWindow(this->width, this->height, this->title.c_str(), nullptr, nullptr); + +} + +void MyVkInstance::initVulkan() { + createInstance(); +#ifdef WITH_VALIDATION_LAYERS + setupDebugMessenger(instance, &debugMessenger); +#endif + createSurface(); + pickPhysicalDevice(); + createLogicalDevice(); +} + +void MyVkInstance::createInstance() { + +#ifdef WITH_VALIDATION_LAYERS + if (!checkValidationLayerSupport()) { + throw std::runtime_error("validation layer support required"); + } +#endif + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "Hello Triangle"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "No Engine"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + + auto extensions = getRequiredExtensions(); + createInfo.enabledExtensionCount = static_cast(extensions.size()); + createInfo.ppEnabledExtensionNames = extensions.data(); + + +#ifdef WITH_VALIDATION_LAYERS + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); +#else + createInfo.enabledLayerCount = 0; + createInfo.ppEnabledLayerNames = nullptr; +#endif + + if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { + throw std::runtime_error("Failed to create instance!"); + } +} + +void MyVkInstance::createSurface() { + if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) { + throw std::runtime_error("Failed to create surface"); + } +} + +void MyVkInstance::pickPhysicalDevice() { + uint32_t deviceCount = 0; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + if (deviceCount == 0) { + throw std::runtime_error("No devices available"); + } + std::vector devices(deviceCount); + vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + for (const auto &pPhysicalDeviceT: devices) { + if (isSuitableDevice(pPhysicalDeviceT, surface)) { + physicalDevice = pPhysicalDeviceT; + break; + } + } + if (physicalDevice == VK_NULL_HANDLE) { + throw std::runtime_error("No suitable device found"); + } +} + +void MyVkInstance::createLogicalDevice() { + this->indices = findQueueFamilies(physicalDevice, surface); + + std::vector queueCreateInfos; + std::set uniqueQueueFamilies = {this->indices.graphicsFamily.value(), this->indices.presentFamily.value()}; + float queuePriority = 1.0f; + 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{}; + + int numel = sizeof(deviceExtensions) / sizeof(void*); + + VkDeviceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.pQueueCreateInfos = queueCreateInfos.data(); + createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); + createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.enabledExtensionCount = static_cast(numel); + createInfo.ppEnabledExtensionNames = deviceExtensions; + createInfo.enabledLayerCount = 0; + + if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { + throw std::runtime_error("Failed to create logical device"); + } + vkGetDeviceQueue(device, this->indices.graphicsFamily.value(), 0, &graphicsQueue); + vkGetDeviceQueue(device, this->indices.presentFamily.value(), 0, &presentQueue); +} + +void MyVkInstance::cleanup() { + vkDestroyDevice(device, nullptr); + vkDestroySurfaceKHR(instance, surface, nullptr); +#ifdef WITH_VALIDATION_LAYERS + DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); +#endif + vkDestroyInstance(instance, nullptr); + glfwDestroyWindow(window); + glfwTerminate(); +} diff --git a/src/MyVkInstance.h b/src/MyVkInstance.h new file mode 100644 index 0000000..6d7899d --- /dev/null +++ b/src/MyVkInstance.h @@ -0,0 +1,53 @@ +// +// Created by rick on 30-05-20. +// + +#ifndef VULKANTEST_MYVKINSTANCE_H +#define VULKANTEST_MYVKINSTANCE_H +#include + +#define GLFW_INCLUDE_VULKAN +#include +#include "queues.h" + + +class MyVkInstance { +public: + MyVkInstance(); + MyVkInstance(int width, int height, char* &title); + + void init(); + + void cleanup(); + + VkInstance instance{}; + VkDevice device{}; + VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; + VkSurfaceKHR surface; + VkQueue graphicsQueue; + VkQueue presentQueue; + GLFWwindow* window{}; + + QueueFamilyIndices indices; +private: + int width{}; + int height{}; + std::string title; + +#ifdef WITH_VALIDATION_LAYERS + VkDebugUtilsMessengerEXT debugMessenger; +#endif + + // window creation + void initWindow(); + + // init vulkan + void initVulkan(); + void createInstance(); + void createSurface(); + void pickPhysicalDevice(); + void createLogicalDevice(); +}; + + +#endif //VULKANTEST_MYVKINSTANCE_H diff --git a/src/queues.cpp b/src/queues.cpp index d17fe2c..9043d7e 100644 --- a/src/queues.cpp +++ b/src/queues.cpp @@ -6,14 +6,14 @@ #include #include -bool checkDeviceExtensionSupport(VkPhysicalDevice device, std::vector deviceExtensions) { +bool checkDeviceExtensionSupport(VkPhysicalDevice device, const char** deviceExtensions, int count) { uint32_t extensionCount; vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); std::vector availableExtensions(extensionCount); vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); - std::set requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); + std::set requiredExtensions(deviceExtensions, deviceExtensions + count); for (const auto& extension : availableExtensions) { requiredExtensions.erase(extension.extensionName); } diff --git a/src/queues.h b/src/queues.h index a6cf2a5..7ec8ac8 100644 --- a/src/queues.h +++ b/src/queues.h @@ -23,7 +23,7 @@ struct SwapChainSupportDetails { std::vector presentModes; }; -bool checkDeviceExtensionSupport(VkPhysicalDevice device, std::vector deviceExtensions); +bool checkDeviceExtensionSupport(VkPhysicalDevice device, const char** deviceExtensions, int size); QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface); SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device, VkSurfaceKHR surface); VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats);