Do vulkan work

This commit is contained in:
Bailey Harrison 2022-09-13 22:43:24 +01:00
parent 07c17687ef
commit 021869a3a1
6 changed files with 202 additions and 119 deletions

View File

@ -98,10 +98,20 @@ if (MINGW)
target_link_libraries(${PROJECT_NAME} PUBLIC mingw32)
endif()
# Vulkan
find_package(Vulkan REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE ${Vulkan_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan)
# GLAD:
set(GLAD_PROFILE "core" CACHE INTERNAL "" FORCE)
set(GLAD_API "gl=3.3" CACHE INTERNAL "" FORCE)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(GLAD_GENERATOR "c-debug" CACHE INTERNAL "" FORCE)
else()
set(GLAD_GENERATOR "c" CACHE INTERNAL "" FORCE)
endif()
set(GLAD_SPEC "gl" CACHE INTERNAL "" FORCE)
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(dependencies/glad)
set_property(TARGET glad PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_libraries(${PROJECT_NAME} PUBLIC glad)
target_include_directories(${PROJECT_NAME} PUBLIC dependencies/glad/include)
# SDL2:
find_package(SDL2)
@ -124,21 +134,6 @@ set(BUILD_SHARED_LIBS OFF)
add_subdirectory(dependencies/glm)
target_include_directories(${PROJECT_NAME} PUBLIC dependencies/glm)
# GLAD:
set(GLAD_PROFILE "core" CACHE INTERNAL "" FORCE)
set(GLAD_API "gl=3.3" CACHE INTERNAL "" FORCE)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(GLAD_GENERATOR "c-debug" CACHE INTERNAL "" FORCE)
else()
set(GLAD_GENERATOR "c" CACHE INTERNAL "" FORCE)
endif()
set(GLAD_SPEC "gl" CACHE INTERNAL "" FORCE)
set(BUILD_SHARED_LIBS OFF)
add_subdirectory(dependencies/glad)
set_property(TARGET glad PROPERTY POSITION_INDEPENDENT_CODE ON)
target_link_libraries(${PROJECT_NAME} PUBLIC glad)
target_include_directories(${PROJECT_NAME} PUBLIC dependencies/glad/include)
# spdlog
set(SPDLOG_BUILD_SHARED ON CACHE INTERNAL "" FORCE)
set(BUILD_SHARED_LIBS ON)

View File

@ -15,7 +15,7 @@ namespace engine::gfx {
private:
class Impl;
std::unique_ptr<Impl> pimpl{};
std::unique_ptr<Impl> pimpl;
};

View File

@ -28,25 +28,10 @@ public:
// Return the title name
std::string getTitle() const;
// Make this window the current OpenGL context.
// This is already done in window initialisation.
void makeContextCurrent();
// Tell the GPU to render the back buffer to the screen.
// Run this on every frame.
void swapBuffers();
// Update the window state to capture any events that have occurred.
// Run this on every frame.
void getInputAndEvents();
// if 'true', swapBuffers() will wait in order to synchronise with the
// monitor's refresh rate.
void setVSync(bool enable);
// Returns true if VSync is enabled.
bool getVSync() const;
glm::ivec2 getViewportSize();
void setTitle(std::string title);
// Hides the window (it will appear closed to the user).
@ -146,7 +131,6 @@ public:
private:
SDL_Window* m_handle;
SDL_GLContext m_glContext;
bool m_shouldClose = false;
@ -158,8 +142,6 @@ public:
// size in screen coordinates
glm::ivec2 m_winSize = glm::vec2(640, 480);
// actual framebuffer size
glm::ivec2 m_fbSize;
// performance counter frequency
uint64_t m_counterFreq;

View File

@ -54,7 +54,7 @@ void Camera::updateCam(glm::mat4 transform)
auto shader = dynamic_cast<Shader*>(lockedPtr.get());
shader->setUniform_m4(VIEW_MAT_UNIFORM, viewMatrix);
shader->setUniform_m4(PROJ_MAT_UNIFORM, m_projMatrix);
shader->setUniform_v2(WINDOW_SIZE_UNIFORM, win.getViewportSize());
// shader->setUniform_v2(WINDOW_SIZE_UNIFORM, win.getViewportSize());
shader->setUniform_v3("lightPos", m_lightPos);
}

View File

@ -6,10 +6,14 @@
#include "window.hpp"
#include "log.hpp"
#include <vulkan/vulkan.h>
#include <assert.h>
#include <iostream>
#include <optional>
namespace engine::gfx {
@ -17,10 +21,43 @@ namespace engine::gfx {
friend Device;
VkInstance m_instance;
#ifndef NDEBUG
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;
Device::Device(AppInfo appInfo, const Window& window)
std::vector<VkLayerProperties> m_layersAvailable{};
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
for (auto it = m_layersAvailable.begin(); it != m_layersAvailable.end(); it++) {
TRACE("Found Vulkan layer: {}, {}", it->layerName, it->description);
if (strncmp(it->layerName, VALIDATION_LAYER_NAME, 256) == 0) {
m_validationLayer = it;
}
}
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)
{
VkResult res;
@ -36,29 +73,140 @@ namespace engine::gfx {
.applicationVersion = VK_MAKE_VERSION(appVersionMajor, appVersionMinor, appVersionPatch),
.pEngineName = "engine",
.engineVersion = VK_MAKE_VERSION(engineVersionMajor, engineVersionMinor, engineVersionPatch),
.apiVersion = VK_VERSION_1_0,
.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
if (m_validationLayer.has_value())
layers.push_back(m_validationLayer.value()->layerName);
#endif
VkInstanceCreateInfo instanceInfo {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.pApplicationInfo = nullptr,
.enabledLayerCount = 0,
.ppEnabledLayerNames = nullptr,
.enabledExtensionCount = 0,
.ppEnabledExtensionNames = nullptr,
.pApplicationInfo = &applicationInfo,
.enabledLayerCount = (uint32_t)layers.size(),
.ppEnabledLayerNames = layers.data(),
.enabledExtensionCount = (uint32_t)extensions.size(),
.ppEnabledExtensionNames = extensions.data(),
};
res = vkCreateInstance(&instanceInfo, nullptr, &pimpl->m_instance);
std::cout << "ERROR CODE: " << res << std::endl;
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);
}
#ifndef NDEBUG
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;
}
#endif
void createDebugMessenger()
{
#ifndef NDEBUG
VkResult res;
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
}
};
Device::Device(AppInfo appInfo, const Window& window) : pimpl(std::make_unique<Impl>())
{
pimpl->findAvailableLayers();
pimpl->createInstance(appInfo, window.getRequiredVulkanExtensions());
pimpl->createDebugMessenger();
}
Device::~Device()
{
vkDestroyInstance(pimpl->m_instance, nullptr);
#ifndef NDEBUG
vkDestroyDebugUtilsMessengerEXT(pimpl->m_instance, pimpl->m_debugMessenger, nullptr);
#endif
}
}

View File

@ -1,7 +1,5 @@
#include "window.hpp"
#include <glad/glad.h>
#include <iostream>
#include <stdexcept>
@ -28,17 +26,13 @@ Window::Window(const std::string& title) : m_title(title)
m_lastFrameStamp = m_startTime - 1;
m_avgFpsStart = m_startTime;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
// create the window
m_handle = SDL_CreateWindow(
m_title.c_str(),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
static_cast<int>(m_winSize.x),
static_cast<int>(m_winSize.y),
SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI);
0);
if (m_handle == NULL) {
SDL_Quit();
throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError()));
@ -54,6 +48,7 @@ Window::Window(const std::string& title) : m_title(title)
const int WINDOWED_MIN_HEIGHT = 480;
SDL_SetWindowMinimumSize(m_handle, WINDOWED_MIN_WIDTH, WINDOWED_MIN_HEIGHT);
/*
m_glContext = SDL_GL_CreateContext(m_handle);
if (m_glContext == NULL) {
SDL_DestroyWindow(m_handle);
@ -66,14 +61,14 @@ Window::Window(const std::string& title) : m_title(title)
SDL_Quit();
throw std::runtime_error("Unable to initialise GLAD");
}
*/
onResize(m_winSize.x, m_winSize.y);
// onResize(m_winSize.x, m_winSize.y);
}
Window::~Window()
{
SDL_GL_DeleteContext(m_glContext);
SDL_DestroyWindow(m_handle);
SDL_Quit();
}
@ -86,13 +81,6 @@ void Window::onResize(Sint32 width, Sint32 height)
m_winSize.x = static_cast<int>(width);
m_winSize.y = static_cast<int>(height);
// get framebuffer size
int fbWidth, fbHeight;
SDL_GL_GetDrawableSize(m_handle, &fbWidth, &fbHeight);
m_fbSize.x = static_cast<int>(fbWidth);
m_fbSize.y = static_cast<int>(fbHeight);
glViewport(0, 0, fbWidth, fbHeight);
m_justResized = true;
}
@ -195,26 +183,13 @@ std::string Window::getTitle() const
return m_title;
}
void Window::makeContextCurrent()
void Window::getInputAndEvents()
{
if (SDL_GL_MakeCurrent(m_handle, m_glContext) != 0) {
throw std::runtime_error("Failed to make GL context current");
}
}
void Window::swapBuffers()
{
#ifndef SDLTEST_NOGFX
SDL_GL_SwapWindow(m_handle);
#endif
m_frames++;
uint64_t currentFrameStamp = getNanos();
m_lastFrameTime = currentFrameStamp - m_lastFrameStamp;
m_lastFrameStamp = currentFrameStamp;
}
void Window::getInputAndEvents()
{
resetInputDeltas();
@ -254,23 +229,6 @@ void Window::getInputAndEvents()
}
void Window::setVSync(bool enable)
{
if (SDL_GL_SetSwapInterval(enable ? 1 : 0) != 0) {
throw std::runtime_error("Failed to set swap interval");
}
}
bool Window::getVSync() const
{
return SDL_GL_GetSwapInterval() == 0 ? false : true;
}
glm::ivec2 Window::getViewportSize()
{
return m_fbSize;
}
void Window::setTitle(std::string title)
{
SDL_SetWindowTitle(m_handle, title.c_str());