#include "engine.h" #include "instance.h" constexpr const char* validationLayerName("VK_LAYER_KHRONOS_validation"); Engine::Engine::Engine() : initialized(false), window(new Window()), instance(nullptr), surface(nullptr), physicalDevice(nullptr), logicalDevice(nullptr), layerNames(), instanceExtensionNames(), deviceExtensionNames(), layers(), instanceExtensions(), deviceExtensions() { addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); } Engine::Engine::~Engine() { delete window; } bool Engine::Engine::enableValidationLayers() const { return instanceExtensionNames.count(VK_EXT_DEBUG_REPORT_EXTENSION_NAME) > 0 && instanceExtensionNames.count(VK_EXT_DEBUG_UTILS_EXTENSION_NAME) > 0 && layerNames.count(validationLayerName) > 0; } void Engine::Engine::addLayer(const std::string& layerName) { if (initialized) throw std::runtime_error("Adding layers to an initialized engine is not supported yet"); layerNames.insert(layerName); } void Engine::Engine::addInstanceExtension(const std::string& extensionName) { if (initialized) throw std::runtime_error("Adding extension to an initialized engine is not supported yet"); std::pair::const_iterator, bool> pair = instanceExtensionNames.insert(extensionName); if (pair.second) instanceExtensions.push_back(pair.first->c_str()); } void Engine::Engine::addDeviceExtension(const std::string& extensionName) { if (initialized) throw std::runtime_error("Adding extension to an initialized engine is not supported yet"); std::pair::const_iterator, bool> pair = deviceExtensionNames.insert(extensionName); if (pair.second) deviceExtensions.push_back(pair.first->c_str()); } void Engine::Engine::enableDebug() { addLayer(validationLayerName); addInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } void Engine::Engine::initVulkan() { instance = new Instance(this); surface = new Surface(instance, window); pickPhysicalDevice(); logicalDevice = new LogicalDevice(physicalDevice, surface, deviceExtensions, layers); logicalDevice->createGraphicsPipeline("shaders/shader.vert.spv", "shaders/shader.frag.spv"); logicalDevice->createSwapChain(); } void Engine::Engine::cleanup() { delete logicalDevice; logicalDevice = nullptr; delete physicalDevice; physicalDevice = nullptr; delete surface; surface = nullptr; delete instance; instance = nullptr; } void Engine::Engine::pickPhysicalDevice() { std::vector devices = instance->enumeratePhysicalDevices(); if (devices.size() == 0) throw std::runtime_error("failed to find GPUs with Vulkan support!"); for (const auto& device : devices) { if (PhysicalDevice::checkDeviceExtensionSupport(device, deviceExtensionNames)) { QueueFamilyIndices indices = surface->findQueueFamilies(device); if (indices.isComplete()) { SwapChainSupportDetails scsd = surface->querySwapChainSupport(device); if (scsd.adequate()) { physicalDevice = new PhysicalDevice(device, indices, scsd); break; } } } } if (physicalDevice == nullptr) throw std::runtime_error("failed to find a suitable GPU!"); } std::vector Engine::Engine::getRequiredVulkanExtensions() const { return window->getRequiredVulkanExtensions(); } void Engine::Engine::run() { initVulkan(); mainLoop(); cleanup(); } void Engine::Engine::mainLoop() { SDL_Event e; bool bQuit = false; //main loop while (!bQuit) { //Handle events on queue while (SDL_PollEvent(&e) != 0) { //close the window when user clicks the X button or alt-f4s if (e.type == SDL_QUIT) bQuit = true; } logicalDevice->drawFrame(); } logicalDevice->waitIdle(); }