window resize handled, instance improved a bit
This commit is contained in:
parent
e114c36690
commit
2b33897b4a
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
project(stories VERSION 0.0.1 LANGUAGES CXX)
|
project(stories VERSION 0.0.1 LANGUAGES CXX)
|
||||||
cmake_policy(SET CMP0076 NEW)
|
cmake_policy(SET CMP0076 NEW)
|
||||||
|
@ -1,51 +1,23 @@
|
|||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "instance.h"
|
|
||||||
|
|
||||||
constexpr const char* validationLayerName("VK_LAYER_KHRONOS_validation");
|
|
||||||
|
|
||||||
Engine::Engine::Engine() :
|
Engine::Engine::Engine() :
|
||||||
initialized(false),
|
initialized(false),
|
||||||
window(new Window()),
|
window(new Window()),
|
||||||
instance(nullptr),
|
instance(new Instance()),
|
||||||
surface(nullptr),
|
surface(nullptr),
|
||||||
physicalDevice(nullptr),
|
physicalDevice(nullptr),
|
||||||
logicalDevice(nullptr),
|
logicalDevice(nullptr),
|
||||||
layerNames(),
|
|
||||||
instanceExtensionNames(),
|
|
||||||
deviceExtensionNames(),
|
deviceExtensionNames(),
|
||||||
layers(),
|
|
||||||
instanceExtensions(),
|
|
||||||
deviceExtensions()
|
deviceExtensions()
|
||||||
{
|
{
|
||||||
addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
addDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::Engine::~Engine() {
|
Engine::Engine::~Engine() {
|
||||||
|
delete instance;
|
||||||
delete window;
|
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) {
|
void Engine::Engine::addDeviceExtension(const std::string& extensionName) {
|
||||||
if (initialized)
|
if (initialized)
|
||||||
throw std::runtime_error("Adding extension to an initialized engine is not supported yet");
|
throw std::runtime_error("Adding extension to an initialized engine is not supported yet");
|
||||||
@ -56,17 +28,15 @@ void Engine::Engine::addDeviceExtension(const std::string& extensionName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Engine::Engine::enableDebug() {
|
void Engine::Engine::enableDebug() {
|
||||||
addLayer(validationLayerName);
|
instance->enableDebug();
|
||||||
addInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
|
|
||||||
addInstanceExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::Engine::initVulkan() {
|
void Engine::Engine::initVulkan() {
|
||||||
instance = new Instance(this);
|
instance->initialize(window->getRequiredVulkanExtensions());
|
||||||
surface = new Surface(instance, window);
|
surface = new Surface(instance, window);
|
||||||
|
|
||||||
pickPhysicalDevice();
|
pickPhysicalDevice();
|
||||||
logicalDevice = new LogicalDevice(physicalDevice, surface, deviceExtensions, layers);
|
logicalDevice = new LogicalDevice(physicalDevice, surface, deviceExtensions, instance->getLayers());
|
||||||
|
|
||||||
logicalDevice->createGraphicsPipeline("shaders/shader.vert.spv", "shaders/shader.frag.spv");
|
logicalDevice->createGraphicsPipeline("shaders/shader.vert.spv", "shaders/shader.frag.spv");
|
||||||
logicalDevice->createSwapChain();
|
logicalDevice->createSwapChain();
|
||||||
@ -82,8 +52,7 @@ void Engine::Engine::cleanup() {
|
|||||||
delete surface;
|
delete surface;
|
||||||
surface = nullptr;
|
surface = nullptr;
|
||||||
|
|
||||||
delete instance;
|
instance->deinitialize();
|
||||||
instance = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::Engine::pickPhysicalDevice() {
|
void Engine::Engine::pickPhysicalDevice() {
|
||||||
@ -108,10 +77,6 @@ void Engine::Engine::pickPhysicalDevice() {
|
|||||||
throw std::runtime_error("failed to find a suitable GPU!");
|
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() {
|
void Engine::Engine::run() {
|
||||||
initVulkan();
|
initVulkan();
|
||||||
mainLoop();
|
mainLoop();
|
||||||
@ -127,8 +92,14 @@ void Engine::Engine::mainLoop() {
|
|||||||
//Handle events on queue
|
//Handle events on queue
|
||||||
while (SDL_PollEvent(&e) != 0) {
|
while (SDL_PollEvent(&e) != 0) {
|
||||||
//close the window when user clicks the X button or alt-f4s
|
//close the window when user clicks the X button or alt-f4s
|
||||||
if (e.type == SDL_QUIT)
|
switch (e.type) {
|
||||||
|
case SDL_QUIT:
|
||||||
bQuit = true;
|
bQuit = true;
|
||||||
|
break;
|
||||||
|
case SDL_WINDOWEVENT:
|
||||||
|
handleWindowEvent(e.window);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logicalDevice->drawFrame();
|
logicalDevice->drawFrame();
|
||||||
@ -136,3 +107,12 @@ void Engine::Engine::mainLoop() {
|
|||||||
|
|
||||||
logicalDevice->waitIdle();
|
logicalDevice->waitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::Engine::handleWindowEvent(const SDL_WindowEvent& e) {
|
||||||
|
switch (e.event) {
|
||||||
|
case SDL_WINDOWEVENT_RESIZED:
|
||||||
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
|
logicalDevice->setResized();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "surface.h"
|
#include "surface.h"
|
||||||
|
#include "instance.h"
|
||||||
#include "physicaldevice.h"
|
#include "physicaldevice.h"
|
||||||
#include "logicaldevice.h"
|
#include "logicaldevice.h"
|
||||||
|
|
||||||
@ -30,21 +31,21 @@ namespace Engine {
|
|||||||
|
|
||||||
const int MAX_FRAMES_IN_FLIGHT = 2;
|
const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
|
|
||||||
class Instance;
|
|
||||||
|
|
||||||
class Engine {
|
class Engine {
|
||||||
friend class Instance;
|
|
||||||
public:
|
public:
|
||||||
Engine();
|
Engine();
|
||||||
~Engine();
|
~Engine();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
bool enableValidationLayers() const;
|
|
||||||
void addLayer(const std::string& layerName);
|
|
||||||
void addInstanceExtension(const std::string& extensionName);
|
|
||||||
void addDeviceExtension(const std::string& extensionName);
|
void addDeviceExtension(const std::string& extensionName);
|
||||||
void enableDebug();
|
void enableDebug();
|
||||||
std::vector<const char *> getRequiredVulkanExtensions() const;
|
|
||||||
|
private:
|
||||||
|
void initVulkan();
|
||||||
|
void mainLoop();
|
||||||
|
void cleanup();
|
||||||
|
void pickPhysicalDevice();
|
||||||
|
void handleWindowEvent(const SDL_WindowEvent& e);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initialized;
|
bool initialized;
|
||||||
@ -53,17 +54,9 @@ private:
|
|||||||
Surface* surface;
|
Surface* surface;
|
||||||
PhysicalDevice* physicalDevice;
|
PhysicalDevice* physicalDevice;
|
||||||
LogicalDevice* logicalDevice;
|
LogicalDevice* logicalDevice;
|
||||||
std::set<std::string> layerNames;
|
|
||||||
std::set<std::string> instanceExtensionNames;
|
|
||||||
std::set<std::string> deviceExtensionNames;
|
std::set<std::string> deviceExtensionNames;
|
||||||
std::vector<const char*> layers;
|
|
||||||
std::vector<const char*> instanceExtensions;
|
|
||||||
std::vector<const char*> deviceExtensions;
|
std::vector<const char*> deviceExtensions;
|
||||||
|
|
||||||
void initVulkan();
|
|
||||||
void mainLoop();
|
|
||||||
void cleanup();
|
|
||||||
void pickPhysicalDevice();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,26 @@
|
|||||||
#include "instance.h"
|
#include "instance.h"
|
||||||
|
|
||||||
#include "engine.h"
|
constexpr const char* validationLayerName("VK_LAYER_KHRONOS_validation");
|
||||||
|
|
||||||
Engine::Instance::Instance(Engine* eng) :
|
Engine::Instance::Instance() :
|
||||||
|
initialized(false),
|
||||||
validationLayersEnabledAndSupported(false),
|
validationLayersEnabledAndSupported(false),
|
||||||
engine(eng),
|
layerNames(),
|
||||||
|
extensionNames(),
|
||||||
|
layers(),
|
||||||
|
extensions(),
|
||||||
vk(),
|
vk(),
|
||||||
debugMessenger()
|
debugMessenger()
|
||||||
{
|
{}
|
||||||
|
|
||||||
|
Engine::Instance::~Instance() {
|
||||||
|
deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::Instance::initialize(const std::vector<const char*>& requiredExtensions) {
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
VkApplicationInfo appInfo {};
|
VkApplicationInfo appInfo {};
|
||||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
appInfo.pApplicationName = "Hello Triangle";
|
appInfo.pApplicationName = "Hello Triangle";
|
||||||
@ -18,19 +31,19 @@ Engine::Instance::Instance(Engine* eng) :
|
|||||||
appInfo.pNext = nullptr;
|
appInfo.pNext = nullptr;
|
||||||
|
|
||||||
//TODO handle exception
|
//TODO handle exception
|
||||||
Support exts = getVulkanExtensions(engine->instanceExtensionNames, engine->getRequiredVulkanExtensions());
|
Support exts = getVulkanExtensions(extensionNames, requiredExtensions);
|
||||||
if (exts.unsupportedCritical.size() > 0) {
|
if (exts.unsupportedCritical.size() > 0) {
|
||||||
std::string error("Unable to create Vulkan instance, following critical extensions are unsupported:\n");
|
std::string error("Unable to create Vulkan instance, following critical extensions are unsupported:\n");
|
||||||
for (const char* ext : exts.unsupportedCritical) {
|
for (const char* ext : exts.unsupportedCritical)
|
||||||
error += "\t" + std::string(ext) + "\n";
|
error += "\t" + std::string(ext) + "\n";
|
||||||
}
|
|
||||||
throw std::runtime_error(error);
|
throw std::runtime_error(error);
|
||||||
}
|
}
|
||||||
//TODO log unsupported;
|
//TODO log unsupported;
|
||||||
exts.logSupported("Applying extensions:");
|
exts.logSupported("Applying extensions:");
|
||||||
|
|
||||||
//TODO handle exception
|
//TODO handle exception
|
||||||
Support layers = getVulkanLayers(engine->layerNames);
|
Support layers = getVulkanLayers(layerNames);
|
||||||
//TODO log unsupported
|
//TODO log unsupported
|
||||||
layers.logSupported("Applying layers:");
|
layers.logSupported("Applying layers:");
|
||||||
|
|
||||||
@ -44,7 +57,7 @@ Engine::Instance::Instance(Engine* eng) :
|
|||||||
createInfo.ppEnabledLayerNames = layers.supported.data();
|
createInfo.ppEnabledLayerNames = layers.supported.data();
|
||||||
|
|
||||||
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
|
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo {};
|
||||||
if (engine->enableValidationLayers()) {
|
if (hasValidationLayers()) {
|
||||||
validationLayersEnabledAndSupported = true; //TODO make sure it's actually supported, this shows that they are just enabled;
|
validationLayersEnabledAndSupported = true; //TODO make sure it's actually supported, this shows that they are just enabled;
|
||||||
populateDebugMessengerCreateInfo(debugCreateInfo, debugCallback);
|
populateDebugMessengerCreateInfo(debugCreateInfo, debugCallback);
|
||||||
createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo;
|
createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo;
|
||||||
@ -72,13 +85,49 @@ Engine::Instance::Instance(Engine* eng) :
|
|||||||
|
|
||||||
if (validationLayersEnabledAndSupported)
|
if (validationLayersEnabledAndSupported)
|
||||||
setupDebugMessenger();
|
setupDebugMessenger();
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::Instance::~Instance() {
|
void Engine::Instance::deinitialize() {
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
if (validationLayersEnabledAndSupported)
|
if (validationLayersEnabledAndSupported)
|
||||||
destroyDebugUtilsMessengerEXT(vk, debugMessenger, nullptr);
|
destroyDebugUtilsMessengerEXT(vk, debugMessenger, nullptr);
|
||||||
|
|
||||||
vkDestroyInstance(vk, nullptr);
|
vkDestroyInstance(vk, nullptr);
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::Instance::addExtension(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 = extensionNames.insert(extensionName);
|
||||||
|
if (pair.second)
|
||||||
|
extensions.push_back(pair.first->c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::Instance::addLayer(const std::string& layerName) {
|
||||||
|
if (initialized)
|
||||||
|
throw std::runtime_error("Adding layers to an initialized engine is not supported yet");
|
||||||
|
|
||||||
|
std::pair<std::set<std::string>::const_iterator, bool> pair = layerNames.insert(layerName);
|
||||||
|
if (pair.second)
|
||||||
|
layers.push_back(pair.first->c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Engine::Instance::hasValidationLayers() {
|
||||||
|
return extensionNames.count(VK_EXT_DEBUG_REPORT_EXTENSION_NAME) > 0 &&
|
||||||
|
extensionNames.count(VK_EXT_DEBUG_UTILS_EXTENSION_NAME) > 0 &&
|
||||||
|
layerNames.count(validationLayerName) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::Instance::enableDebug() {
|
||||||
|
addLayer(validationLayerName);
|
||||||
|
addExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
|
||||||
|
addExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::Instance::setupDebugMessenger() {
|
void Engine::Instance::setupDebugMessenger() {
|
||||||
@ -108,3 +157,6 @@ std::vector<VkPhysicalDevice> Engine::Instance::enumeratePhysicalDevices() const
|
|||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<const char *> Engine::Instance::getLayers() const {
|
||||||
|
return layers;
|
||||||
|
}
|
||||||
|
@ -2,30 +2,40 @@
|
|||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
namespace Engine {
|
namespace Engine {
|
||||||
|
|
||||||
class Engine;
|
|
||||||
class Window;
|
|
||||||
class Surface;
|
class Surface;
|
||||||
|
|
||||||
class Instance {
|
class Instance {
|
||||||
friend class Engine;
|
|
||||||
friend class Surface;
|
friend class Surface;
|
||||||
public:
|
public:
|
||||||
Instance(Engine* engine);
|
Instance();
|
||||||
~Instance();
|
~Instance();
|
||||||
|
|
||||||
|
void initialize(const std::vector<const char*>& requiredExtensions);
|
||||||
|
void deinitialize();
|
||||||
|
void addLayer(const std::string& layerName);
|
||||||
|
void addExtension(const std::string& extensionName);
|
||||||
|
void enableDebug();
|
||||||
|
std::vector<const char*> getLayers() const;
|
||||||
|
|
||||||
std::vector<VkPhysicalDevice> enumeratePhysicalDevices() const;
|
std::vector<VkPhysicalDevice> enumeratePhysicalDevices() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupDebugMessenger();
|
void setupDebugMessenger();
|
||||||
|
bool hasValidationLayers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool initialized;
|
||||||
bool validationLayersEnabledAndSupported;
|
bool validationLayersEnabledAndSupported;
|
||||||
Engine* engine;
|
std::set<std::string> layerNames;
|
||||||
|
std::set<std::string> extensionNames;
|
||||||
|
std::vector<const char*> layers;
|
||||||
|
std::vector<const char*> extensions;
|
||||||
VkInstance vk;
|
VkInstance vk;
|
||||||
VkDebugUtilsMessengerEXT debugMessenger;
|
VkDebugUtilsMessengerEXT debugMessenger;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "logicaldevice.h"
|
#include "logicaldevice.h"
|
||||||
|
|
||||||
#include "swapchain.h"
|
#include "swapchain.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
constexpr int MAX_FRAMES_IN_FLIGHT = 2;
|
constexpr int MAX_FRAMES_IN_FLIGHT = 2;
|
||||||
constexpr float queuePriority = 1.0f;
|
constexpr float queuePriority = 1.0f;
|
||||||
@ -269,6 +270,10 @@ void Engine::LogicalDevice::drawFrame() {
|
|||||||
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::LogicalDevice::setResized() {
|
||||||
|
framebufferResized = true;
|
||||||
|
}
|
||||||
|
|
||||||
VkExtent2D Engine::LogicalDevice::chooseSwapExtent() const {
|
VkExtent2D Engine::LogicalDevice::chooseSwapExtent() const {
|
||||||
return surface->chooseSwapExtent(phys->swapChainSupport.capabilities);
|
return surface->chooseSwapExtent(phys->swapChainSupport.capabilities);
|
||||||
}
|
}
|
||||||
@ -564,5 +569,6 @@ void Engine::LogicalDevice::recordCommandBuffer(VkCommandBuffer commandBuffer, u
|
|||||||
void Engine::LogicalDevice::recreateSwapChain() {
|
void Engine::LogicalDevice::recreateSwapChain() {
|
||||||
surface->waitForResize();
|
surface->waitForResize();
|
||||||
waitIdle();
|
waitIdle();
|
||||||
|
phys->recreateSwapChainSupportDetails(surface);
|
||||||
createSwapChain();
|
createSwapChain();
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,9 @@
|
|||||||
#include "surface.h"
|
#include "surface.h"
|
||||||
|
|
||||||
namespace Engine {
|
namespace Engine {
|
||||||
class Engine;
|
|
||||||
class SwapChain;
|
class SwapChain;
|
||||||
|
|
||||||
class LogicalDevice {
|
class LogicalDevice {
|
||||||
friend class Engine;
|
|
||||||
public:
|
public:
|
||||||
LogicalDevice(
|
LogicalDevice(
|
||||||
PhysicalDevice* physicalDevice,
|
PhysicalDevice* physicalDevice,
|
||||||
@ -28,6 +26,7 @@ public:
|
|||||||
void clearSwapChain();
|
void clearSwapChain();
|
||||||
void createGraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath);
|
void createGraphicsPipeline(const std::string& vertexShaderPath, const std::string& fragmentShaderPath);
|
||||||
void recreateSwapChain();
|
void recreateSwapChain();
|
||||||
|
void setResized();
|
||||||
|
|
||||||
void drawFrame();
|
void drawFrame();
|
||||||
|
|
||||||
|
@ -32,3 +32,7 @@ bool Engine::PhysicalDevice::checkDeviceExtensionSupport(VkPhysicalDevice device
|
|||||||
|
|
||||||
return requiredExtensions.empty();
|
return requiredExtensions.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::PhysicalDevice::recreateSwapChainSupportDetails(const Surface* surface) {
|
||||||
|
swapChainSupport = surface->querySwapChainSupport(vk);
|
||||||
|
}
|
||||||
|
@ -7,21 +7,22 @@
|
|||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "surface.h"
|
||||||
|
|
||||||
namespace Engine {
|
namespace Engine {
|
||||||
class Engine;
|
|
||||||
class LogicalDevice;
|
class LogicalDevice;
|
||||||
|
|
||||||
class PhysicalDevice {
|
class PhysicalDevice {
|
||||||
friend class Engine;
|
|
||||||
friend class LogicalDevice;
|
friend class LogicalDevice;
|
||||||
public:
|
public:
|
||||||
PhysicalDevice(VkPhysicalDevice raw, const QueueFamilyIndices& indices, const SwapChainSupportDetails& swapChainSupport);
|
PhysicalDevice(VkPhysicalDevice raw, const QueueFamilyIndices& indices, const SwapChainSupportDetails& swapChainSupport);
|
||||||
|
|
||||||
|
void recreateSwapChainSupportDetails(const Surface* surface);
|
||||||
|
|
||||||
static bool checkDeviceExtensionSupport(VkPhysicalDevice device, std::set<std::string> requiredExtensions);
|
static bool checkDeviceExtensionSupport(VkPhysicalDevice device, std::set<std::string> requiredExtensions);
|
||||||
|
|
||||||
const QueueFamilyIndices indices;
|
const QueueFamilyIndices indices;
|
||||||
const SwapChainSupportDetails swapChainSupport;
|
SwapChainSupportDetails swapChainSupport;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkPhysicalDevice vk;
|
VkPhysicalDevice vk;
|
||||||
|
@ -86,3 +86,6 @@ VkExtent2D Engine::Surface::waitForResize() const {
|
|||||||
return window->waitForResize();
|
return window->waitForResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkExtent2D Engine::Surface::getSize() const {
|
||||||
|
return window->getSize();
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@ public:
|
|||||||
|
|
||||||
VkExtent2D waitForResize() const;
|
VkExtent2D waitForResize() const;
|
||||||
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) const;
|
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) const;
|
||||||
|
VkExtent2D getSize() const;
|
||||||
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const SwapChainSupportDetails& swapChainSupport) const;
|
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const SwapChainSupportDetails& swapChainSupport) const;
|
||||||
bool isDeviceSutable(VkPhysicalDevice device) const;
|
bool isDeviceSutable(VkPhysicalDevice device) const;
|
||||||
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) const;
|
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) const;
|
||||||
|
@ -10,6 +10,21 @@ Engine::SwapChain::SwapChain(LogicalDevice* logical):
|
|||||||
imageViews(),
|
imageViews(),
|
||||||
frameBuffers()
|
frameBuffers()
|
||||||
{
|
{
|
||||||
|
create();
|
||||||
|
}
|
||||||
|
|
||||||
|
Engine::SwapChain::SwapChain(LogicalDevice* logical, const VkExtent2D& extent):
|
||||||
|
logical(logical),
|
||||||
|
vk(),
|
||||||
|
images(),
|
||||||
|
extent(extent),
|
||||||
|
imageViews(),
|
||||||
|
frameBuffers()
|
||||||
|
{
|
||||||
|
create();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::SwapChain::create() {
|
||||||
VkResult result = logical->createVkSwapChain(extent, vk);
|
VkResult result = logical->createVkSwapChain(extent, vk);
|
||||||
|
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
@ -31,6 +46,7 @@ Engine::SwapChain::SwapChain(LogicalDevice* logical):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Engine::SwapChain::~SwapChain() {
|
Engine::SwapChain::~SwapChain() {
|
||||||
for (VkFramebuffer& buffer : frameBuffers)
|
for (VkFramebuffer& buffer : frameBuffers)
|
||||||
logical->destroyVkFrameBuffer(buffer);
|
logical->destroyVkFrameBuffer(buffer);
|
||||||
|
@ -11,11 +11,15 @@ class SwapChain {
|
|||||||
friend class LogicalDevice;
|
friend class LogicalDevice;
|
||||||
public:
|
public:
|
||||||
SwapChain(LogicalDevice* logical);
|
SwapChain(LogicalDevice* logical);
|
||||||
|
SwapChain(LogicalDevice* logical, const VkExtent2D& extent);
|
||||||
~SwapChain();
|
~SwapChain();
|
||||||
|
|
||||||
VkExtent2D getExtent() const;
|
VkExtent2D getExtent() const;
|
||||||
VkFramebuffer getFrameBuffer(uint32_t index);
|
VkFramebuffer getFrameBuffer(uint32_t index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void create();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LogicalDevice* logical;
|
LogicalDevice* logical;
|
||||||
VkSwapchainKHR vk;
|
VkSwapchainKHR vk;
|
||||||
|
@ -10,19 +10,18 @@ Engine::Support Engine::getVulkanLayers(const std::set<std::string>& requestedLa
|
|||||||
Engine::Support result;
|
Engine::Support result;
|
||||||
if (!discoveredLayers) {
|
if (!discoveredLayers) {
|
||||||
std::vector<VkLayerProperties> props = getAvailableVulkanLayers();
|
std::vector<VkLayerProperties> props = getAvailableVulkanLayers();
|
||||||
for (const VkLayerProperties& prop : props) {
|
for (const VkLayerProperties& prop : props)
|
||||||
availableLayers.insert(std::make_pair(prop.layerName, prop));
|
availableLayers.insert(std::make_pair(prop.layerName, prop));
|
||||||
}
|
|
||||||
discoveredLayers = true;
|
discoveredLayers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const std::string& ext : requestedLayers) {
|
for (const std::string& ext : requestedLayers) {
|
||||||
if (availableLayers.count(ext) > 0) {
|
if (availableLayers.count(ext) > 0)
|
||||||
result.supported.push_back(ext.c_str());
|
result.supported.push_back(ext.c_str());
|
||||||
} else {
|
else
|
||||||
result.unsupported.push_back(ext.c_str());
|
result.unsupported.push_back(ext.c_str());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -34,27 +33,25 @@ Engine::Support Engine::getVulkanExtensions(
|
|||||||
Support result;
|
Support result;
|
||||||
if (!discoveredExtensions) {
|
if (!discoveredExtensions) {
|
||||||
std::vector<VkExtensionProperties> props = getAvailableVulkanExtensions();
|
std::vector<VkExtensionProperties> props = getAvailableVulkanExtensions();
|
||||||
for (const VkExtensionProperties& prop : props) {
|
for (const VkExtensionProperties& prop : props)
|
||||||
availableExtensions.insert(std::make_pair(prop.extensionName, prop));
|
availableExtensions.insert(std::make_pair(prop.extensionName, prop));
|
||||||
}
|
|
||||||
discoveredExtensions = true;
|
discoveredExtensions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const char* ext : criticalExtensions) {
|
for (const char* ext : criticalExtensions) {
|
||||||
if (availableExtensions.count(ext) > 0) {
|
if (availableExtensions.count(ext) > 0)
|
||||||
result.supported.push_back(ext);
|
result.supported.push_back(ext);
|
||||||
} else {
|
else
|
||||||
result.unsupportedCritical.push_back(ext);
|
result.unsupportedCritical.push_back(ext);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (const std::string& ext : requestedExtensions) {
|
for (const std::string& ext : requestedExtensions) {
|
||||||
if (availableExtensions.count(ext) > 0) {
|
if (availableExtensions.count(ext) > 0)
|
||||||
result.supported.push_back(ext.c_str());
|
result.supported.push_back(ext.c_str());
|
||||||
} else {
|
else
|
||||||
result.unsupported.push_back(ext.c_str());
|
result.unsupported.push_back(ext.c_str());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -62,15 +59,13 @@ Engine::Support Engine::getVulkanExtensions(
|
|||||||
std::vector<VkExtensionProperties> Engine::getAvailableVulkanExtensions() {
|
std::vector<VkExtensionProperties> Engine::getAvailableVulkanExtensions() {
|
||||||
unsigned int extCount = 0;
|
unsigned int extCount = 0;
|
||||||
VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
|
VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
|
||||||
if (res != VK_SUCCESS) {
|
if (res != VK_SUCCESS)
|
||||||
throw std::runtime_error("unable to query vulkan extension property count");
|
throw std::runtime_error("unable to query vulkan extension property count");
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<VkExtensionProperties> extensions(extCount);
|
std::vector<VkExtensionProperties> extensions(extCount);
|
||||||
res = vkEnumerateInstanceExtensionProperties(nullptr, &extCount, extensions.data());
|
res = vkEnumerateInstanceExtensionProperties(nullptr, &extCount, extensions.data());
|
||||||
if (res != VK_SUCCESS) {
|
if (res != VK_SUCCESS)
|
||||||
throw std::runtime_error("unable to retrieve vulkan instance layer names");
|
throw std::runtime_error("unable to retrieve vulkan instance layer names");
|
||||||
}
|
|
||||||
|
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
@ -95,15 +90,13 @@ void Engine::populateDebugMessengerCreateInfo(
|
|||||||
std::vector<VkLayerProperties> Engine::getAvailableVulkanLayers() {
|
std::vector<VkLayerProperties> Engine::getAvailableVulkanLayers() {
|
||||||
unsigned int layerCount = 0;
|
unsigned int layerCount = 0;
|
||||||
VkResult res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
VkResult res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
||||||
if (res != VK_SUCCESS) {
|
if (res != VK_SUCCESS)
|
||||||
throw std::runtime_error("unable to query vulkan instance layer property count");
|
throw std::runtime_error("unable to query vulkan instance layer property count");
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<VkLayerProperties> layers(layerCount);
|
std::vector<VkLayerProperties> layers(layerCount);
|
||||||
res = vkEnumerateInstanceLayerProperties(&layerCount, layers.data());
|
res = vkEnumerateInstanceLayerProperties(&layerCount, layers.data());
|
||||||
if (res != VK_SUCCESS) {
|
if (res != VK_SUCCESS)
|
||||||
throw std::runtime_error("unable to retrieve vulkan instance layer names");
|
throw std::runtime_error("unable to retrieve vulkan instance layer names");
|
||||||
}
|
|
||||||
|
|
||||||
return layers;
|
return layers;
|
||||||
}
|
}
|
||||||
@ -175,20 +168,18 @@ std::vector<char> Engine::readFile(const std::string& filename) {
|
|||||||
|
|
||||||
VkSurfaceFormatKHR Engine::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
|
VkSurfaceFormatKHR Engine::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
|
||||||
for (const VkSurfaceFormatKHR& availableFormat : availableFormats) {
|
for (const VkSurfaceFormatKHR& availableFormat : availableFormats) {
|
||||||
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||||
return availableFormat;
|
return availableFormat;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return availableFormats[0];
|
return availableFormats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPresentModeKHR Engine::chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {
|
VkPresentModeKHR Engine::chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {
|
||||||
for (const auto& availablePresentMode : availablePresentModes) {
|
for (const auto& availablePresentMode : availablePresentModes) {
|
||||||
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
|
||||||
return availablePresentMode;
|
return availablePresentMode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return VK_PRESENT_MODE_FIFO_KHR;
|
return VK_PRESENT_MODE_FIFO_KHR;
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,11 @@
|
|||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
Engine::Window::Window(uint32_t width, uint32_t height) :
|
Engine::Window::Window(uint32_t width, uint32_t height) :
|
||||||
sdl(createWindow(width, height)),
|
sdl(createWindow(width, height)),
|
||||||
extent({width, height})
|
extent({width, height})
|
||||||
{
|
{}
|
||||||
|
|
||||||
//glfwSetWindowUserPointer(window, this);
|
|
||||||
//glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static void framebufferResizeCallback(SDL_Window* window, int width, int height) {
|
|
||||||
// auto app = reinterpret_cast<HelloTriangleApplication*>(glfwGetWindowUserPointer(window));
|
|
||||||
// app->framebufferResized = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
Engine::Window::~Window() {
|
Engine::Window::~Window() {
|
||||||
SDL_DestroyWindow(sdl);
|
SDL_DestroyWindow(sdl);
|
||||||
@ -27,7 +20,7 @@ SDL_Window* Engine::Window::createWindow(uint32_t width, uint32_t height) {
|
|||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
SDL_WINDOW_VULKAN
|
SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
return wnd;
|
return wnd;
|
||||||
@ -59,6 +52,18 @@ VkExtent2D Engine::Window::getDrawableSize() const {
|
|||||||
return actualExtent;
|
return actualExtent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkExtent2D Engine::Window::getSize() const {
|
||||||
|
int width, height;
|
||||||
|
SDL_GetWindowSize(sdl, &width, &height);
|
||||||
|
|
||||||
|
VkExtent2D actualExtent = {
|
||||||
|
static_cast<uint32_t>(width),
|
||||||
|
static_cast<uint32_t>(height)
|
||||||
|
};
|
||||||
|
|
||||||
|
return actualExtent;
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::Window::createSurface(VkInstance instance, VkSurfaceKHR* out) const {
|
void Engine::Window::createSurface(VkInstance instance, VkSurfaceKHR* out) const {
|
||||||
if (SDL_Vulkan_CreateSurface(sdl, instance, out) != SDL_TRUE) {
|
if (SDL_Vulkan_CreateSurface(sdl, instance, out) != SDL_TRUE) {
|
||||||
throw std::runtime_error("failed to create window surface!");
|
throw std::runtime_error("failed to create window surface!");
|
||||||
@ -74,6 +79,7 @@ VkExtent2D Engine::Window::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capa
|
|||||||
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
||||||
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||||
|
|
||||||
|
std::cout << actualExtent.width << ":" << actualExtent.height << std::endl;
|
||||||
return actualExtent;
|
return actualExtent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ public:
|
|||||||
|
|
||||||
std::vector<const char *> getRequiredVulkanExtensions() const;
|
std::vector<const char *> getRequiredVulkanExtensions() const;
|
||||||
VkExtent2D waitForResize() const;
|
VkExtent2D waitForResize() const;
|
||||||
|
VkExtent2D getSize() const;
|
||||||
VkExtent2D getDrawableSize() const;
|
VkExtent2D getDrawableSize() const;
|
||||||
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) const;
|
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) const;
|
||||||
void createSurface(VkInstance instance, VkSurfaceKHR* out) const;
|
void createSurface(VkInstance instance, VkSurfaceKHR* out) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user