From 07c17687efd732926830de82c765435c5efbe54c Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Tue, 13 Sep 2022 19:25:18 +0100 Subject: [PATCH] Begin vulkan impl --- CMakeLists.txt | 20 ++++---- config.h.in | 2 +- graphics/CMakeLists.txt | 26 ----------- graphics/include/gfx_api.h | 13 ------ graphics/include/gfx_device.hpp | 30 ------------ graphics/src/gfx_device.cpp | 7 --- include/engine.hpp | 38 +++------------ {graphics/include => include}/gfx.hpp | 0 include/gfx_device.hpp | 22 +++++++++ include/logger.hpp | 45 ++++++++++++++++++ include/window.hpp | 3 ++ src/engine.cpp | 16 +++++++ src/gfx_device_vulkan.cpp | 66 +++++++++++++++++++++++++++ src/window.cpp | 18 ++++++++ 14 files changed, 189 insertions(+), 117 deletions(-) delete mode 100644 graphics/CMakeLists.txt delete mode 100644 graphics/include/gfx_api.h delete mode 100644 graphics/include/gfx_device.hpp delete mode 100644 graphics/src/gfx_device.cpp rename {graphics/include => include}/gfx.hpp (100%) create mode 100644 include/gfx_device.hpp create mode 100644 include/logger.hpp create mode 100644 src/engine.cpp create mode 100644 src/gfx_device_vulkan.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a066fe..1180d53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,8 @@ project(engine LANGUAGES CXX add_library(${PROJECT_NAME} SHARED + "src/engine.cpp" "src/window.cpp" - "src/input.cpp" #TODO make input_manager "src/object.cpp" @@ -30,6 +30,8 @@ add_library(${PROJECT_NAME} SHARED "src/resource_manager.cpp" + "src/gfx_device_vulkan.cpp" + # PUBLIC API "include/engine_api.h" @@ -63,6 +65,9 @@ add_library(${PROJECT_NAME} SHARED "include/resource_manager.hpp" + "include/gfx.hpp" + "include/gfx_device.hpp" + ) # compiling options: @@ -84,13 +89,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE src) configure_file(config.h.in config.h) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) -# project submodules: - -add_subdirectory(graphics) -target_include_directories(${PROJECT_NAME} PUBLIC graphics/include) -target_link_libraries(${PROJECT_NAME} PUBLIC graphics) - - +target_compile_definitions(${PROJECT_NAME} PRIVATE "ENGINE_BUILD_VULKAN") # external libraries: @@ -99,6 +98,11 @@ 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) + # SDL2: find_package(SDL2) if (SDL2_FOUND) diff --git a/config.h.in b/config.h.in index 797c5ba..39107e3 100644 --- a/config.h.in +++ b/config.h.in @@ -1,3 +1,3 @@ #pragma once -#define ENGINE_VERSION @PROJECT_VERSION@ +#define ENGINE_VERSION "@PROJECT_VERSION@" diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt deleted file mode 100644 index bf83c4a..0000000 --- a/graphics/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.4) - -# options - -project(graphics LANGUAGES CXX) - -add_library(${PROJECT_NAME} STATIC - - "src/gfx_device.cpp" - - # PUBLIC API - - "include/gfx_api.h" - "include/gfx.hpp" - "include/gfx_device.hpp" - -) - -# compiling options: - -target_compile_definitions(${PROJECT_NAME} PRIVATE DEFINITIONS "GFX_EXPORTS") - -target_include_directories(${PROJECT_NAME} PUBLIC include) -target_include_directories(${PROJECT_NAME} PRIVATE src) - -# libraries: diff --git a/graphics/include/gfx_api.h b/graphics/include/gfx_api.h deleted file mode 100644 index e153b5e..0000000 --- a/graphics/include/gfx_api.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#ifndef GFX_API -# ifdef _MSC_VER -# ifdef GFX_EXPORTS -# define GFX_API __declspec(dllexport) -# else -# define GFX_API __declspec(dllimport) -# endif -# else -# define GFX_API -# endif -#endif diff --git a/graphics/include/gfx_device.hpp b/graphics/include/gfx_device.hpp deleted file mode 100644 index 7688aa2..0000000 --- a/graphics/include/gfx_device.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "gfx_api.h" - -#include "gfx.hpp" - -namespace gfx { - - // Do not use a pointer to this class, always cast to the proper implementation to avoid V-Table overhead - struct GFX_API IDevice { - - - - virtual void setViewport(uint32_t top_left_x, uint32_t top_left_y, uint32_t width, uint32_t height) = 0; - - virtual bool createShader(ShaderType type, const char* source, Shader& out) = 0; - virtual bool createProgram(int count, const Shader* shaders, Program& out) = 0; - - virtual bool createBuffer(BufferType type, const void* data, Buffer& out) = 0; - virtual void bufferData(const void* data, Buffer buffer) = 0; - virtual void bufferSubData(uint32_t offset, uint32_t size, const void* data, Buffer buffer) = 0; - - virtual void drawElements(Primitive primitive, IndexBufferFormat format, uint32_t count, uint32_t offset) = 0; - virtual void drawArrays() = 0; - - }; - - - -} diff --git a/graphics/src/gfx_device.cpp b/graphics/src/gfx_device.cpp deleted file mode 100644 index 9013025..0000000 --- a/graphics/src/gfx_device.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "gfx_device.hpp" - -#include - -namespace gfx { - -} diff --git a/include/engine.hpp b/include/engine.hpp index 42e6df4..9d2eaf8 100644 --- a/include/engine.hpp +++ b/include/engine.hpp @@ -8,38 +8,12 @@ namespace engine { - // To be executed in the target application, NOT engine.dll - void setupLog(const char* appName) - { + struct AppInfo { + const char* name; + const char* version; + }; - const std::string LOG_FILENAME{ std::string(appName) + ".log"}; -#ifdef NDEBUG - // RELEASE - const std::filesystem::path log_path{ std::filesystem::temp_directory_path() / LOG_FILENAME }; -#else - // DEBUG - const std::filesystem::path log_path{ LOG_FILENAME }; -#endif + bool versionFromCharArray(const char* version, int* major, int* minor, int* patch); - std::vector sinks; - - sinks.emplace_back(std::make_shared(log_path.string(), true)); - -#ifndef NDEBUG - // DEBUG - sinks.emplace_back(std::make_shared()); -#endif - - auto logger = std::make_shared("sdltest", sinks.begin(), sinks.end()); - - logger->set_level(spdlog::level::trace); - - spdlog::register_logger(logger); - spdlog::set_default_logger(logger); - - INFO("Created log with path: {}", log_path.string()); - - } - -} \ No newline at end of file +} diff --git a/graphics/include/gfx.hpp b/include/gfx.hpp similarity index 100% rename from graphics/include/gfx.hpp rename to include/gfx.hpp diff --git a/include/gfx_device.hpp b/include/gfx_device.hpp new file mode 100644 index 0000000..3a454e5 --- /dev/null +++ b/include/gfx_device.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "engine_api.h" + +#include "engine.hpp" + +class Window; + +namespace engine::gfx { + + struct ENGINE_API Device { + + Device(AppInfo appInfo, const Window& window); + ~Device(); + + private: + class Impl; + std::unique_ptr pimpl{}; + + }; + +} diff --git a/include/logger.hpp b/include/logger.hpp new file mode 100644 index 0000000..9ab1d84 --- /dev/null +++ b/include/logger.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include + +#include "log.hpp" +#include +#include + +namespace engine { + + // To be executed in the target application, NOT engine.dll + void setupLog(const char* appName) + { + + const std::string LOG_FILENAME{ std::string(appName) + ".log"}; + +#ifdef NDEBUG + // RELEASE + const std::filesystem::path log_path{ std::filesystem::temp_directory_path() / LOG_FILENAME }; +#else + // DEBUG + const std::filesystem::path log_path{ LOG_FILENAME }; +#endif + + std::vector sinks; + + sinks.emplace_back(std::make_shared(log_path.string(), true)); + +#ifndef NDEBUG + // DEBUG + sinks.emplace_back(std::make_shared()); +#endif + + auto logger = std::make_shared("sdltest", sinks.begin(), sinks.end()); + + logger->set_level(spdlog::level::trace); + + spdlog::register_logger(logger); + spdlog::set_default_logger(logger); + + INFO("Created log with path: {}", log_path.string()); + + } + +} diff --git a/include/window.hpp b/include/window.hpp index 7856d63..1079d83 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -13,6 +13,7 @@ #include #include +#include ENGINE_API extern const uint64_t BILLION; @@ -138,6 +139,8 @@ public: bool infoBox(const std::string& title, const std::string& msg); + std::vector getRequiredVulkanExtensions() const; + /* STATIC METHODS */ static void errorBox(const std::string& message); diff --git a/src/engine.cpp b/src/engine.cpp new file mode 100644 index 0000000..0f50ff9 --- /dev/null +++ b/src/engine.cpp @@ -0,0 +1,16 @@ +#include "engine.hpp" + +namespace engine { + +bool versionFromCharArray(const char* version, int* major, int* minor, int* patch) +{ + if (sscanf(version, "%d.%d.%d", major, minor, patch) != 3) { + *major = 0; + *minor = 0; + *patch = 0; + return false; + } + return true; +} + +} diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp new file mode 100644 index 0000000..67448e3 --- /dev/null +++ b/src/gfx_device_vulkan.cpp @@ -0,0 +1,66 @@ +#ifdef ENGINE_BUILD_VULKAN + +#include "gfx_device.hpp" + +#include "config.h" + +#include "window.hpp" + +#include + +#include +#include + +namespace engine::gfx { + + class Device::Impl { + friend Device; + + VkInstance m_instance; + + }; + + Device::Device(AppInfo appInfo, const Window& window) + { + VkResult res; + + 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_VERSION_1_0, + }; + + VkInstanceCreateInfo instanceInfo{ + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .pApplicationInfo = nullptr, + .enabledLayerCount = 0, + .ppEnabledLayerNames = nullptr, + .enabledExtensionCount = 0, + .ppEnabledExtensionNames = nullptr, + }; + + res = vkCreateInstance(&instanceInfo, nullptr, &pimpl->m_instance); + std::cout << "ERROR CODE: " << res << std::endl; + assert(res == VK_SUCCESS); + + } + + Device::~Device() + { + vkDestroyInstance(pimpl->m_instance, nullptr); + } + +} + +#endif diff --git a/src/window.cpp b/src/window.cpp index 1dddc44..87a6669 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -5,6 +5,10 @@ #include #include +#ifdef ENGINE_BUILD_VULKAN +#include +#endif + const uint64_t BILLION = 1000000000; Window::Window(const std::string& title) : m_title(title) @@ -485,6 +489,20 @@ bool Window::infoBox(const std::string& title, const std::string& msg) } } +std::vector Window::getRequiredVulkanExtensions() const +{ +#ifdef ENGINE_BUILD_VULKAN + unsigned int sdlExtensionCount = 0; + SDL_Vulkan_GetInstanceExtensions(m_handle, &sdlExtensionCount, nullptr); + std::vector requiredExtensions(sdlExtensionCount); + SDL_Vulkan_GetInstanceExtensions(m_handle, &sdlExtensionCount, requiredExtensions.data()); + + return requiredExtensions; +#else + return std::vector{}; +#endif +} + /* STATIC METHODS */ // Display an error message box