139 lines
4.0 KiB
C++
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();
|
|
}
|