This commit is contained in:
Bailey Harrison 2022-09-17 01:22:35 +01:00
parent 2c4a47541d
commit 40c0c024a1
6 changed files with 308 additions and 235 deletions

View File

@ -1,11 +1,5 @@
#pragma once #pragma once
#include <filesystem>
#include "log.hpp"
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
namespace engine { namespace engine {
struct AppInfo { struct AppInfo {

View File

@ -4,13 +4,16 @@
#include "engine.hpp" #include "engine.hpp"
class Window; #include <SDL_video.h>
#include <memory>
namespace engine::gfx { namespace engine::gfx {
struct ENGINE_API Device { struct ENGINE_API Device {
Device(AppInfo appInfo, const Window& window); Device(AppInfo appInfo, SDL_Window* window);
~Device(); ~Device();
private: private:

View File

@ -124,77 +124,76 @@ public:
bool infoBox(const std::string& title, const std::string& msg); bool infoBox(const std::string& title, const std::string& msg);
std::vector<const char*> getRequiredVulkanExtensions() const;
/* STATIC METHODS */ /* STATIC METHODS */
static void errorBox(const std::string& message); static void errorBox(const std::string& message);
private: public:
SDL_Window* m_handle; SDL_Window* m_handle;
bool m_shouldClose = false; private:
std::string m_title; bool m_shouldClose = false;
bool m_fullscreen = false; std::string m_title;
bool m_justResized = false;
bool m_keyboardFocus = true;
// size in screen coordinates bool m_fullscreen = false;
glm::ivec2 m_winSize = glm::vec2(640, 480); bool m_justResized = false;
bool m_keyboardFocus = true;
// performance counter frequency // size in screen coordinates
uint64_t m_counterFreq; glm::ivec2 m_winSize = glm::vec2(640, 480);
// number of frames swapped // performance counter frequency
uint64_t m_frames = 0; uint64_t m_counterFreq;
// frame count offset for fpsAvg
uint64_t m_avgFpsStartCount = 0;
// in nanoseconds
uint64_t m_startTime;
// in nanoseconds
uint64_t m_lastFrameStamp;
// in nanoseconds; elapsed time between frames
uint64_t m_lastFrameTime = 1; // not 0 to avoid division by zero
// in nanoseconds
uint64_t m_avgFpsStart;
// input stuff // number of frames swapped
uint64_t m_frames = 0;
// frame count offset for fpsAvg
uint64_t m_avgFpsStartCount = 0;
// in nanoseconds
uint64_t m_startTime;
// in nanoseconds
uint64_t m_lastFrameStamp;
// in nanoseconds; elapsed time between frames
uint64_t m_lastFrameTime = 1; // not 0 to avoid division by zero
// in nanoseconds
uint64_t m_avgFpsStart;
enum class ButtonDelta { // input stuff
SAME = 0,
PRESSED,
RELEASED
};
struct { enum class ButtonDelta {
std::array<bool, SDL_NUM_SCANCODES> keys; SAME = 0,
std::array<enum ButtonDelta, SDL_NUM_SCANCODES> deltas; PRESSED,
} m_keyboard{ }; RELEASED
};
struct { struct {
std::array<bool, static_cast<int>(inputs::MouseButton::M_SIZE)> buttons; std::array<bool, SDL_NUM_SCANCODES> keys;
std::array<enum ButtonDelta, 8> deltas; std::array<enum ButtonDelta, SDL_NUM_SCANCODES> deltas;
Sint32 x; } m_keyboard{ };
Sint32 y;
Sint32 dx;
Sint32 dy;
float xscroll;
float yscroll;
bool captured = false;
} m_mouse{ };
// private methods struct {
std::array<bool, static_cast<int>(inputs::MouseButton::M_SIZE)> buttons;
std::array<enum ButtonDelta, 8> deltas;
Sint32 x;
Sint32 y;
Sint32 dx;
Sint32 dy;
float xscroll;
float yscroll;
bool captured = false;
} m_mouse{ };
void onResize(Sint32 width, Sint32 height); // private methods
void resetInputDeltas();
// event methods (like callbacks) void onResize(Sint32 width, Sint32 height);
void resetInputDeltas();
void onWindowEvent(SDL_WindowEvent& e); // event methods (like callbacks)
void onKeyEvent(SDL_KeyboardEvent& e);
void onMouseButtonEvent(SDL_MouseButtonEvent& e);
void onMouseMotionEvent(SDL_MouseMotionEvent& e);
void onMouseWheelEvent(SDL_MouseWheelEvent& e);
void onWindowEvent(SDL_WindowEvent& e);
void onKeyEvent(SDL_KeyboardEvent& e);
void onMouseButtonEvent(SDL_MouseButtonEvent& e);
void onMouseMotionEvent(SDL_MouseMotionEvent& e);
void onMouseWheelEvent(SDL_MouseWheelEvent& e);
}; };

View File

@ -1,5 +1,7 @@
#include "engine.hpp" #include "engine.hpp"
#include <cstdio>
namespace engine { namespace engine {
bool versionFromCharArray(const char* version, int* major, int* minor, int* patch) bool versionFromCharArray(const char* version, int* major, int* minor, int* patch)

View File

@ -3,14 +3,13 @@
#include "gfx_device.hpp" #include "gfx_device.hpp"
#include "config.h" #include "config.h"
#include "window.hpp"
#include "log.hpp" #include "log.hpp"
#define VOLK_IMPLEMENTATION #define VOLK_IMPLEMENTATION
#include "volk.h" #include "volk.h"
#include <SDL_vulkan.h>
#include <assert.h> #include <assert.h>
#include <iostream> #include <iostream>
@ -18,194 +17,286 @@
namespace engine::gfx { namespace engine::gfx {
static std::vector<const char*> getRequiredVulkanExtensions(SDL_Window* window)
{
#ifdef ENGINE_BUILD_VULKAN
SDL_bool res;
unsigned int sdlExtensionCount = 0;
res = SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, nullptr);
assert(res == SDL_TRUE);
std::vector<const char*> requiredExtensions(sdlExtensionCount);
res = SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, requiredExtensions.data());
assert(res == SDL_TRUE);
return requiredExtensions;
#else
return std::vector<const char*>{};
#endif
}
static VkBool32 debugMessenger(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
{
std::string msgType{};
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
msgType += " (GENERAL)";
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
msgType += " (PERF.)";
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
msgType += " (VALID.)";
switch (messageSeverity) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
TRACE("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
INFO("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
WARN("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
break;
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
ERROR("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage);
break;
default:
break;
}
return VK_FALSE;
}
class Device::Impl { class Device::Impl {
friend Device; friend Device;
VkInstance m_instance; public:
#ifndef NDEBUG Impl(AppInfo appInfo, SDL_Window* window)
VkDebugUtilsMessengerEXT m_debugMessenger;
#endif
static constexpr const char * VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation";
static constexpr VkDebugUtilsMessageSeverityFlagBitsEXT MESSAGE_LEVEL = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
std::vector<VkLayerProperties> m_layersAvailable{};
std::optional<std::vector<VkLayerProperties>::iterator> m_validationLayer;
void findAvailableLayers()
{ {
VkResult res; m_instance = std::make_unique<Instance>(appInfo, getRequiredVulkanExtensions(window));
uint32_t layerCount;
res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
assert(res == VK_SUCCESS);
m_layersAvailable.resize(layerCount);
res = vkEnumerateInstanceLayerProperties(&layerCount, m_layersAvailable.data());
assert(res == VK_SUCCESS);
#ifndef NDEBUG #ifndef NDEBUG
for (auto it = m_layersAvailable.begin(); it != m_layersAvailable.end(); it++) { m_debugMessenger = std::make_unique<DebugMessenger>(m_instance->getHandle());
TRACE("Found Vulkan layer: {}, {}", it->layerName, it->description); #endif
if (strncmp(it->layerName, VALIDATION_LAYER_NAME, 256) == 0) { }
m_validationLayer = it;
private:
// VkSurfaceKHR m_surface;
static constexpr VkDebugUtilsMessageSeverityFlagBitsEXT MESSAGE_LEVEL = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
class Instance {
public:
Instance(AppInfo appInfo, const std::vector<const char*>& windowExtensions)
{
VkResult res;
findAvailableLayers();
int appVersionMajor, appVersionMinor, appVersionPatch;
assert(versionFromCharArray(appInfo.version, &appVersionMajor, &appVersionMinor, &appVersionPatch));
int engineVersionMajor, engineVersionMinor, engineVersionPatch;
assert(versionFromCharArray(ENGINE_VERSION, &engineVersionMajor, &engineVersionMinor, &engineVersionPatch));
VkApplicationInfo applicationInfo{
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = appInfo.name,
.applicationVersion = VK_MAKE_VERSION(appVersionMajor, appVersionMinor, appVersionPatch),
.pEngineName = "engine",
.engineVersion = VK_MAKE_VERSION(engineVersionMajor, engineVersionMinor, engineVersionPatch),
.apiVersion = VK_API_VERSION_1_0,
};
// make a list of all extensions to use
std::vector<const char*> extensions{};
extensions.insert(extensions.end(), windowExtensions.begin(), windowExtensions.end());
std::vector<const char*> layers{};
if (m_validationLayer.has_value()) {
layers.push_back(m_validationLayer.value()->layerName);
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
} }
}
if (m_validationLayer.has_value() == false) {
WARN("The validation layer was not found. Continuing.");
}
#endif
}
void createInstance(AppInfo appInfo, const std::vector<const char*>& windowExtensions) VkInstanceCreateInfo instanceInfo{
{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
VkResult res; .pNext = nullptr,
.flags = 0,
.pApplicationInfo = &applicationInfo,
.enabledLayerCount = (uint32_t)layers.size(),
.ppEnabledLayerNames = layers.data(),
.enabledExtensionCount = (uint32_t)extensions.size(),
.ppEnabledExtensionNames = extensions.data(),
};
int appVersionMajor, appVersionMinor, appVersionPatch; if (m_validationLayer.has_value()) {
assert(versionFromCharArray(appInfo.version, &appVersionMajor, &appVersionMinor, &appVersionPatch)); VkDebugUtilsMessengerCreateInfoEXT debugMessengerCreateInfo = DebugMessenger::getCreateInfo();
int engineVersionMajor, engineVersionMinor, engineVersionPatch; instanceInfo.pNext = &debugMessengerCreateInfo;
assert(versionFromCharArray(ENGINE_VERSION, &engineVersionMajor, &engineVersionMinor, &engineVersionPatch)); }
VkApplicationInfo applicationInfo {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = appInfo.name,
.applicationVersion = VK_MAKE_VERSION(appVersionMajor, appVersionMinor, appVersionPatch),
.pEngineName = "engine",
.engineVersion = VK_MAKE_VERSION(engineVersionMajor, engineVersionMinor, engineVersionPatch),
.apiVersion = VK_API_VERSION_1_0,
};
// make a list of all extensions to use
std::vector<const char*> extensions{};
extensions.insert(extensions.end(), windowExtensions.begin(), windowExtensions.end());
#ifndef NDEBUG
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif
std::vector<const char*> layers{};
#ifndef NDEBUG #ifndef NDEBUG
if (m_validationLayer.has_value()) for (const char* ext : extensions) {
layers.push_back(m_validationLayer.value()->layerName); TRACE("Using Vulkan instance extension: {}", ext);
}
#endif #endif
VkInstanceCreateInfo instanceInfo { res = vkCreateInstance(&instanceInfo, nullptr, &m_handle);
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, if (res == VK_ERROR_INCOMPATIBLE_DRIVER) {
.pNext = nullptr, CRITICAL("The graphics driver is incompatible with vulkan");
.flags = 0, throw std::runtime_error("Graphics driver is incompatible with Vulkan");
.pApplicationInfo = &applicationInfo, }
.enabledLayerCount = (uint32_t)layers.size(), assert(res == VK_SUCCESS);
.ppEnabledLayerNames = layers.data(),
.enabledExtensionCount = (uint32_t)extensions.size(), volkLoadInstance(m_handle);
.ppEnabledExtensionNames = extensions.data(),
};
res = vkCreateInstance(&instanceInfo, nullptr, &m_instance);
if (res == VK_ERROR_INCOMPATIBLE_DRIVER) {
CRITICAL("The graphics driver is incompatible with vulkan");
throw std::runtime_error("Graphics driver is incompatible with Vulkan");
} }
assert(res == VK_SUCCESS);
} ~Instance()
{
vkDestroyInstance(m_handle, nullptr);
}
VkInstance getHandle()
{
return m_handle;
}
private:
VkInstance m_handle;
std::vector<VkLayerProperties> m_layersAvailable{};
static constexpr const char* VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation";
std::optional<std::vector<VkLayerProperties>::iterator> m_validationLayer;
void findAvailableLayers()
{
VkResult res;
uint32_t layerCount;
res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
assert(res == VK_SUCCESS);
m_layersAvailable.resize(layerCount);
res = vkEnumerateInstanceLayerProperties(&layerCount, m_layersAvailable.data());
assert(res == VK_SUCCESS);
#ifndef NDEBUG #ifndef NDEBUG
static VkBool32 debugMessenger( // find validation layer and print all layers to log
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, for (auto it = m_layersAvailable.begin(); it != m_layersAvailable.end(); it++) {
VkDebugUtilsMessageTypeFlagsEXT messageTypes, // TRACE("Found Vulkan layer: {}, {}", it->layerName, it->description);
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, if (strncmp(it->layerName, VALIDATION_LAYER_NAME, 256) == 0) {
void* pUserData) m_validationLayer = it;
{ }
}
if (m_validationLayer.has_value() == false) {
CRITICAL("The validation layer was not found. Quitting.");
throw std::runtime_error("Validation layer not found");
}
#endif
}
std::string msgType{}; };
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) #ifndef NDEBUG
msgType += " (GENERAL)"; class DebugMessenger {
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
msgType += " (PERF.)";
if (messageTypes & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
msgType += " (VALID.)";
switch (messageSeverity) { public:
DebugMessenger(const VkInstance& instance) : m_instance(instance)
{
VkDebugUtilsMessengerCreateInfoEXT createInfo = getCreateInfo();
VkResult res = vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &m_debugMessenger);
assert(res == VK_SUCCESS);
}
~DebugMessenger()
{
vkDestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr);
}
static VkDebugUtilsMessengerCreateInfoEXT getCreateInfo()
{
VkDebugUtilsMessengerCreateInfoEXT createInfo{
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = 0,
.messageSeverity = 0,
.messageType =
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
.pfnUserCallback = debugMessenger,
.pUserData = nullptr,
};
switch (MESSAGE_LEVEL) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
TRACE("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage); createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
break; // fall-through
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
INFO("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage); createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
break; // fall-through
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
WARN("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage); createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
break; // fall-through
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
ERROR("VULKAN MESSAGE{}: ID: {} MSG: {}", msgType, pCallbackData->pMessageIdName, pCallbackData->pMessage); createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
break; // fall-through
default: default:
break; break;
}
return createInfo;
} }
return VK_FALSE;
} private:
VkDebugUtilsMessengerEXT m_debugMessenger;
const VkInstance& m_instance;
};
#endif #endif
void createDebugMessenger() std::unique_ptr<Instance> m_instance;
{
#ifndef NDEBUG #ifndef NDEBUG
VkResult res; std::unique_ptr<DebugMessenger> m_debugMessenger;
if (m_validationLayer.has_value() == false) return;
VkDebugUtilsMessengerCreateInfoEXT createInfo {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.pNext = nullptr,
.flags = 0,
.messageSeverity = 0,
.messageType =
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
.pfnUserCallback = debugMessenger,
.pUserData = nullptr,
};
switch (MESSAGE_LEVEL) {
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
// fall-through
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
// fall-through
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
// fall-through
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
createInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
// fall-through
default:
break;
}
res = vkCreateDebugUtilsMessengerEXT(m_instance, &createInfo, nullptr, &m_debugMessenger);
assert(res == VK_SUCCESS);
#endif #endif
/*
void createSurface(SDL_Window* window)
{
if (SDL_Vulkan_CreateSurface(window, m_instance, &m_surface) == false) {
CRITICAL("Unable to create window surface");
throw std::runtime_error("Unable to create window surface");
}
} }
*/
}; };
Device::Device(AppInfo appInfo, SDL_Window* window)
Device::Device(AppInfo appInfo, const Window& window) : pimpl(std::make_unique<Impl>())
{ {
pimpl->findAvailableLayers(); VkResult res;
pimpl->createInstance(appInfo, window.getRequiredVulkanExtensions()); res = volkInitialize();
pimpl->createDebugMessenger(); if (res == VK_ERROR_INITIALIZATION_FAILED) {
CRITICAL("Unable to load vulkan, is it installed?");
throw std::runtime_error("Unable to load vulkan, is it installed?");
}
assert(res == VK_SUCCESS);
pimpl = std::make_unique<Impl>(appInfo, window);
//pimpl->createDebugMessenger();
} }
Device::~Device() Device::~Device()
{ {
vkDestroyInstance(pimpl->m_instance, nullptr); //pimpl->cleanup();
#ifndef NDEBUG
vkDestroyDebugUtilsMessengerEXT(pimpl->m_instance, pimpl->m_debugMessenger, nullptr);
#endif
} }
} }

View File

@ -1,12 +1,10 @@
#include "window.hpp" #include "window.hpp"
#include "log.hpp"
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#ifdef ENGINE_BUILD_VULKAN
#include <SDL2/SDL_vulkan.h>
#endif
const uint64_t BILLION = 1000000000; const uint64_t BILLION = 1000000000;
Window::Window(const std::string& title) : m_title(title) Window::Window(const std::string& title) : m_title(title)
@ -32,7 +30,7 @@ Window::Window(const std::string& title) : m_title(title)
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
static_cast<int>(m_winSize.x), static_cast<int>(m_winSize.x),
static_cast<int>(m_winSize.y), static_cast<int>(m_winSize.y),
0); SDL_WINDOW_VULKAN | SDL_WINDOW_SHOWN);
if (m_handle == NULL) { if (m_handle == NULL) {
SDL_Quit(); SDL_Quit();
throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError())); throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError()));
@ -447,20 +445,6 @@ bool Window::infoBox(const std::string& title, const std::string& msg)
} }
} }
std::vector<const char*> Window::getRequiredVulkanExtensions() const
{
#ifdef ENGINE_BUILD_VULKAN
unsigned int sdlExtensionCount = 0;
SDL_Vulkan_GetInstanceExtensions(m_handle, &sdlExtensionCount, nullptr);
std::vector<const char*> requiredExtensions(sdlExtensionCount);
SDL_Vulkan_GetInstanceExtensions(m_handle, &sdlExtensionCount, requiredExtensions.data());
return requiredExtensions;
#else
return std::vector<const char*>{};
#endif
}
/* STATIC METHODS */ /* STATIC METHODS */
// Display an error message box // Display an error message box