stories/engine/engine.cpp

139 lines
4.0 KiB
C++

#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<std::set<std::string>::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<std::set<std::string>::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<VkPhysicalDevice> 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<const char *> 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();
}