diff --git a/ConjureEngine/CMakeLists.txt b/ConjureEngine/CMakeLists.txt index 813d541..bc6f39d 100644 --- a/ConjureEngine/CMakeLists.txt +++ b/ConjureEngine/CMakeLists.txt @@ -6,13 +6,14 @@ project(ConjureEngine) set(HEADER_FILES src/ConjureEngine/Application.h - src/ConjureEngine/Engine.h + src/ConjureEngine/ConjureEngine.h + src/ConjureEngine/VulkanContext.h src/ConjureEngine/Window.h ) set(SOURCES_FILES src/ConjureEngine/Application.cpp - src/ConjureEngine/Engine.cpp + src/ConjureEngine/VulkanContext.cpp src/ConjureEngine/Window.cpp ) diff --git a/ConjureEngine/docs/.gitkeep b/ConjureEngine/docs/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/ConjureEngine/docs/class.mmd b/ConjureEngine/docs/class.mmd new file mode 100644 index 0000000..2b7b43a --- /dev/null +++ b/ConjureEngine/docs/class.mmd @@ -0,0 +1,24 @@ +classDiagram + namespace ConjureEngine { + class Application { + + Run() int + + Tick(double deltaTime) void + } + + class Window { + + std::shared_ptr~SDL_Window~ m_window; + + std::shared_ptr~VulkanContext~ m_vulkanContext; + } + + class VulkanContext { + - uint32_t m_extensionCount + - char** m_extensionNames + - VkInstance m_vkInst + - uint32_t m_physicalDeviceCount + - std::vector~VkPhysicalDevice~ m_physicalDevices + - VkPhysicalDevice m_selectedDevice + - uint32_t m_queueFamilyCount + } + } + + Window "1" *-- "1" VulkanContext \ No newline at end of file diff --git a/ConjureEngine/src/ConjureEngine/Application.cpp b/ConjureEngine/src/ConjureEngine/Application.cpp index e0417f4..5333878 100644 --- a/ConjureEngine/src/ConjureEngine/Application.cpp +++ b/ConjureEngine/src/ConjureEngine/Application.cpp @@ -5,4 +5,10 @@ #include "Application.h" namespace ConjureEngine { -} // ConjureEngine \ No newline at end of file + Application::Application(const ApplicationInfo &applicationInfo): m_applicationInfo(applicationInfo) { + } + + int Application::Run() const { return 0; } + void Application::Tick(double deltaTime) const {} + +} // ConjureEngine diff --git a/ConjureEngine/src/ConjureEngine/Application.h b/ConjureEngine/src/ConjureEngine/Application.h index 161eb0e..0c2840b 100644 --- a/ConjureEngine/src/ConjureEngine/Application.h +++ b/ConjureEngine/src/ConjureEngine/Application.h @@ -4,10 +4,26 @@ #pragma once +#include "PCH.h" +#include "Window.h" + namespace ConjureEngine { + struct ApplicationInfo { + WindowInfo window{"", 0, 0, 0, 0}; + }; -class Application { + class Application { + public: + explicit Application(const ApplicationInfo &applicationInfo); + virtual ~Application() = default; -}; + virtual int Run() const; -} // ConjureEngine \ No newline at end of file + virtual void Tick(double deltaTime) const; + + protected: + public: + protected: + ApplicationInfo m_applicationInfo; + }; +} // ConjureEngine diff --git a/ConjureEngine/src/ConjureEngine/ConjureEngine.h b/ConjureEngine/src/ConjureEngine/ConjureEngine.h new file mode 100644 index 0000000..af90929 --- /dev/null +++ b/ConjureEngine/src/ConjureEngine/ConjureEngine.h @@ -0,0 +1,4 @@ +#pragma once + +#include "Application.h" +#include "Window.h" diff --git a/ConjureEngine/src/ConjureEngine/Engine.cpp b/ConjureEngine/src/ConjureEngine/Engine.cpp deleted file mode 100644 index 693210c..0000000 --- a/ConjureEngine/src/ConjureEngine/Engine.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// -// Created by Jimmy Tremblay-bernier on 2024-11-14. -// -#include "Engine.h" diff --git a/ConjureEngine/src/ConjureEngine/Engine.h b/ConjureEngine/src/ConjureEngine/Engine.h deleted file mode 100644 index 8ff00e5..0000000 --- a/ConjureEngine/src/ConjureEngine/Engine.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "glm/glm.hpp" - -namespace ConjureEngine { - -} diff --git a/ConjureEngine/src/ConjureEngine/PCH.h b/ConjureEngine/src/ConjureEngine/PCH.h index f1f8d61..d31b963 100644 --- a/ConjureEngine/src/ConjureEngine/PCH.h +++ b/ConjureEngine/src/ConjureEngine/PCH.h @@ -18,4 +18,8 @@ #include "SDL2/SDL_video.h" // VULKAN -#include "Vulkan/vulkan.h" \ No newline at end of file +#include "vulkan/vulkan.h" +#include "vulkan/vulkan_core.h" +#ifdef __APPLE__ + #include "vulkan/vulkan_metal.h" +#endif \ No newline at end of file diff --git a/ConjureEngine/src/ConjureEngine/VulkanContext.cpp b/ConjureEngine/src/ConjureEngine/VulkanContext.cpp new file mode 100644 index 0000000..e07fc94 --- /dev/null +++ b/ConjureEngine/src/ConjureEngine/VulkanContext.cpp @@ -0,0 +1,125 @@ +// +// Created by Jimmy Tremblay-bernier on 2024-11-22. +// + +#include "VulkanContext.h" + +#ifdef __APPLE__ + #define VK_USE_PLATFORM_METAL_EXT +#endif + +namespace ConjureEngine { + VulkanContext::VulkanContext(SDL_Window* window, const VkApplicationInfo& appInfo) { + // LOAD THE EXTENSIONS + SDL_Vulkan_GetInstanceExtensions(window, &m_extensionCount, nullptr); + m_extensionNames.reserve(m_extensionCount); + SDL_Vulkan_GetInstanceExtensions(window, &m_extensionCount, m_extensionNames.data()); + + + // Fill the instance create info using appInfo + VkInstanceCreateInfo vulkanInfos{}; + vulkanInfos.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + vulkanInfos.pApplicationInfo = &appInfo; + + // ENABLE THE REQUIRED EXTENSIONS + this->EnableGlobalExtentions(window, vulkanInfos); + + // CREATE VULKAN INSTANCE + vkCreateInstance(&vulkanInfos, nullptr, &m_vkInst); + + // LOAD THE PHYSICAL DEVICES (GPUs) + vkEnumeratePhysicalDevices(m_vkInst, &m_physicalDeviceCount, nullptr); + m_physicalDevices = std::vector(m_physicalDeviceCount); + vkEnumeratePhysicalDevices(m_vkInst, &m_physicalDeviceCount, m_physicalDevices.data()); + + // SELECT THE MAIN GPU (WE COULD HAVE A SMARTER SELECTION LATER) + m_selectedPhysicalDevice = m_physicalDevices[0]; + + // LOAD THE FAMILLY QUEUE PROPERTIES + vkGetPhysicalDeviceQueueFamilyProperties(m_selectedPhysicalDevice, &m_queueFamilyCount, nullptr); + std::vector queueFamilies(m_queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(m_selectedPhysicalDevice, &m_queueFamilyCount, queueFamilies.data()); + + // CREATE THE SURFACE FOR RENDERING + SDL_Vulkan_CreateSurface(window, m_vkInst, &m_surface); + + // ??? + uint32_t graphicsQueueIndex = UINT32_MAX; + uint32_t presentQueueIndex = UINT32_MAX; + VkBool32 support; + uint32_t i = 0; + for (VkQueueFamilyProperties queueFamily: queueFamilies) { + if (graphicsQueueIndex == UINT32_MAX && queueFamily.queueCount > 0 && queueFamily.queueFlags & + VK_QUEUE_GRAPHICS_BIT) + graphicsQueueIndex = i; + if (presentQueueIndex == UINT32_MAX) { + vkGetPhysicalDeviceSurfaceSupportKHR(m_selectedPhysicalDevice, i, m_surface, &support); + if (support) + presentQueueIndex = i; + } + ++i; + } + + // + float queuePriority = 1.0f; + m_deviceQueueCreateInfo = { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType + nullptr, // pNext + 0, // flags + graphicsQueueIndex, // graphicsQueueIndex + 1, // queueCount + &queuePriority, // pQueuePriorities + }; + + // FETCH THE PHYSICAL DEVICES FEATURES + VkPhysicalDeviceFeatures deviceFeatures = {}; + const char *deviceExtensionNames[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; + m_deviceCreateInfo = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType + nullptr, // pNext + 0, // flags + 1, // queueCreateInfoCount + &m_deviceQueueCreateInfo, // pQueueCreateInfos + 0, // enabledLayerCount + nullptr, // ppEnabledLayerNames + 1, // enabledExtensionCount + deviceExtensionNames, // ppEnabledExtensionNames + &deviceFeatures, // pEnabledFeatures + }; + + + // CREATE VIRTUAL DEVICE FOR RENDERING + vkCreateDevice(m_selectedPhysicalDevice, &m_deviceCreateInfo, nullptr, &m_device); + + vkGetDeviceQueue(m_device, graphicsQueueIndex, 0, &m_graphicQueue); + vkGetDeviceQueue(m_device, presentQueueIndex, 0, &m_presentQueue); + + const std::string error = SDL_GetError(); + if(!error.empty()) { + SDL_Log("Initialized with errors: %s", error.c_str()); + } + else { + SDL_Log("Initialized without errors"); + } + } + + void VulkanContext::EnableGlobalExtentions(SDL_Window* window, VkInstanceCreateInfo &vulkanInfos) { + SDL_Vulkan_GetInstanceExtensions(window, &m_extensionCount, nullptr); + this->m_extensionNames.reserve(m_extensionCount); + SDL_Vulkan_GetInstanceExtensions(window, &m_extensionCount, m_extensionNames.data()); + + #ifdef __APPLE__ + this->m_extensionNames.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + this->m_extensionNames.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); + vulkanInfos.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + #endif + + vulkanInfos.enabledExtensionCount = static_cast(this->m_extensionNames.size()); + vulkanInfos.ppEnabledExtensionNames = this->m_extensionNames.data(); + } + + VulkanContext::~VulkanContext() { + vkDestroyDevice(m_device, nullptr); + vkDestroyInstance(m_vkInst, nullptr); + } +} // ConjureEngine diff --git a/ConjureEngine/src/ConjureEngine/VulkanContext.h b/ConjureEngine/src/ConjureEngine/VulkanContext.h new file mode 100644 index 0000000..18bcd29 --- /dev/null +++ b/ConjureEngine/src/ConjureEngine/VulkanContext.h @@ -0,0 +1,31 @@ +// +// Created by Jimmy Tremblay-bernier on 2024-11-22. +// + +#pragma once + +namespace ConjureEngine { +#include "PCH.h" + + class VulkanContext { + public: + explicit VulkanContext(SDL_Window* window, const VkApplicationInfo& appInfo); + ~VulkanContext(); + void EnableGlobalExtentions(SDL_Window* window, VkInstanceCreateInfo &vulkanInfos); + + private: + uint32_t m_extensionCount{0}; + std::vector m_extensionNames; + VkInstance m_vkInst{}; + uint32_t m_physicalDeviceCount{0}; + std::vector m_physicalDevices; + VkPhysicalDevice m_selectedPhysicalDevice; + uint32_t m_queueFamilyCount{0}; + VkSurfaceKHR m_surface; + VkDeviceQueueCreateInfo m_deviceQueueCreateInfo; + VkDeviceCreateInfo m_deviceCreateInfo; + VkDevice m_device; + VkQueue m_graphicQueue; + VkQueue m_presentQueue; + }; +} // ConjureEngine diff --git a/ConjureEngine/src/ConjureEngine/Window.cpp b/ConjureEngine/src/ConjureEngine/Window.cpp index 0dde45f..61cd396 100644 --- a/ConjureEngine/src/ConjureEngine/Window.cpp +++ b/ConjureEngine/src/ConjureEngine/Window.cpp @@ -7,113 +7,32 @@ namespace ConjureEngine { Window::Window(const WindowInfo& windowInfo) { + // INIT WINDOW SDL_Init(SDL_INIT_VIDEO); SDL_Vulkan_LoadLibrary(nullptr); - m_window = std::shared_ptr( - SDL_CreateWindow(windowInfo.title.c_str(), 0, 0, windowInfo.width, windowInfo.height, SDL_WINDOW_SHOWN |SDL_WINDOW_VULKAN) - ); + m_window = SDL_CreateWindow(windowInfo.title.c_str(), 0, 0, windowInfo.width, windowInfo.height, SDL_WINDOW_SHOWN |SDL_WINDOW_VULKAN); + // Fill the application information + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = windowInfo.title.c_str(); + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "Conjure Engine"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_0; - SDL_Vulkan_GetInstanceExtensions(m_window.get(), &m_extensionCount, nullptr); - m_extensionNames = new const char *[m_extensionCount]; - SDL_Vulkan_GetInstanceExtensions(m_window.get(), &m_extensionCount, m_extensionNames); - const VkInstanceCreateInfo instInfo = { - VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType - nullptr, // pNext - 0, // flags - nullptr, // pApplicationInfo - 0, // enabledLayerCount - nullptr, // ppEnabledLayerNames - m_extensionCount, // enabledExtensionCount - m_extensionNames, // ppEnabledExtensionNames - }; - vkCreateInstance(&instInfo, nullptr, &m_vkInst); + // INIT VULKAN + m_vulkanContext = new VulkanContext(m_window, appInfo); + } - vkEnumeratePhysicalDevices(m_vkInst, &m_physicalDeviceCount, nullptr); - m_physicalDevices = std::vector(m_physicalDeviceCount); + Window::~Window() { + delete m_vulkanContext; - vkEnumeratePhysicalDevices(m_vkInst, &m_physicalDeviceCount, m_physicalDevices.data()); + SDL_DestroyWindow(m_window); + SDL_Vulkan_UnloadLibrary(); + SDL_Quit(); - // TODO - I'M AT THIS POINT - VkPhysicalDevice physicalDevice = m_physicalDevices[0]; - - uint32_t queueFamilyCount; - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr); - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilies.data()); - - VkSurfaceKHR surface; - SDL_Vulkan_CreateSurface(window, vkInst, &surface); - - uint32_t graphicsQueueIndex = UINT32_MAX; - uint32_t presentQueueIndex = UINT32_MAX; - VkBool32 support; - uint32_t i = 0; - for (VkQueueFamilyProperties queueFamily : queueFamilies) { - if (graphicsQueueIndex == UINT32_MAX && queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) - graphicsQueueIndex = i; - if (presentQueueIndex == UINT32_MAX) { - vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &support); - if(support) - presentQueueIndex = i; - } - ++i; - } - - float queuePriority = 1.0f; - VkDeviceQueueCreateInfo queueInfo = { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType - nullptr, // pNext - 0, // flags - graphicsQueueIndex, // graphicsQueueIndex - 1, // queueCount - &queuePriority, // pQueuePriorities - }; - - VkPhysicalDeviceFeatures deviceFeatures = {}; - const char* deviceExtensionNames[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; - VkDeviceCreateInfo createInfo = { - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType - nullptr, // pNext - 0, // flags - 1, // queueCreateInfoCount - &queueInfo, // pQueueCreateInfos - 0, // enabledLayerCount - nullptr, // ppEnabledLayerNames - 1, // enabledExtensionCount - deviceExtensionNames, // ppEnabledExtensionNames - &deviceFeatures, // pEnabledFeatures - }; - VkDevice device; - vkCreateDevice(physicalDevice, &createInfo, nullptr, &device); - - VkQueue graphicsQueue; - vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue); - - VkQueue presentQueue; - vkGetDeviceQueue(device, presentQueueIndex, 0, &presentQueue); - - SDL_Log("Initialized with errors: %s", SDL_GetError()); - - bool running = true; - while(running) { - SDL_Event windowEvent; - while(SDL_PollEvent(&windowEvent)) - if(windowEvent.type == SDL_QUIT) { - running = false; - break; - } - } - - vkDestroyDevice(device, nullptr); - vkDestroyInstance(vkInst, nullptr); - SDL_DestroyWindow(window); - SDL_Vulkan_UnloadLibrary(); - SDL_Quit(); - - SDL_Log("Cleaned up with errors: %s", SDL_GetError()); - - return 0; + SDL_Log("Cleaned up with errors: %s", SDL_GetError()); } } // ConjureEngine \ No newline at end of file diff --git a/ConjureEngine/src/ConjureEngine/Window.h b/ConjureEngine/src/ConjureEngine/Window.h index ebc1b7e..f5ce802 100644 --- a/ConjureEngine/src/ConjureEngine/Window.h +++ b/ConjureEngine/src/ConjureEngine/Window.h @@ -4,26 +4,30 @@ #pragma once -namespace ConjureEngine { +#include "PCH.h" +#include "VulkanContext.h" -struct WindowInfo { - std::string title; - int width; - int height; -}; +namespace ConjureEngine { + struct WindowInfo { + std::string title; + int x; + int y; + int width; + int height; + }; class Window { public: explicit Window(const WindowInfo& windowInfo); + ~Window(); + + const std::shared_ptr& GetWindow() const; + const std::shared_ptr& GetVulkanContext() const; private: public: private: - std::shared_ptr m_window; - uint32_t m_extensionCount{0}; - const char** m_extensionNames{nullptr}; - VkInstance m_vkInst; - uint32_t m_physicalDeviceCount{0}; - std::vector m_physicalDevices; + SDL_Window* m_window; + VulkanContext* m_vulkanContext; }; } // ConjureEngine \ No newline at end of file diff --git a/Demo1/CMakeLists.txt b/Demo1/CMakeLists.txt index f1b17b4..63941d0 100644 --- a/Demo1/CMakeLists.txt +++ b/Demo1/CMakeLists.txt @@ -3,7 +3,9 @@ project(Demo1) set(CMAKE_CXX_STANDARD 20) -add_executable(${PROJECT_NAME} src/main.cpp) +add_executable(${PROJECT_NAME} src/main.cpp + src/Demo1.cpp + src/Demo1.h) target_link_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/ConjureEngine) diff --git a/Demo1/src/Demo1.cpp b/Demo1/src/Demo1.cpp new file mode 100644 index 0000000..49512bd --- /dev/null +++ b/Demo1/src/Demo1.cpp @@ -0,0 +1,42 @@ +// +// Created by Jimmy Tremblay-bernier on 2024-11-22. +// + +#include "Demo1.h" +#include "ConjureEngine/ConjureEngine.h" + +namespace Demo1 { + Demo1::Demo1(): ConjureEngine::Application( + { + {"Demo1", 0, 0, 1920, 1080} + } + ) { + } + + + int Demo1::Run() const { + ConjureEngine::Window window(m_applicationInfo.window); + + bool running = true; + while (running) { + SDL_Event windowEvent; + uint64_t timeSinceStart = SDL_GetTicks64(); + + while (SDL_PollEvent(&windowEvent)) { + if (windowEvent.type == SDL_QUIT) { + running = false; + break; + } + } + + this->Tick((double)timeSinceStart/1000.0f); + } + + return 0; + } + + void Demo1::Tick(double deltaTime) const { + + } + +} // Demo1 diff --git a/Demo1/src/Demo1.h b/Demo1/src/Demo1.h new file mode 100644 index 0000000..c339852 --- /dev/null +++ b/Demo1/src/Demo1.h @@ -0,0 +1,17 @@ +// +// Created by Jimmy Tremblay-bernier on 2024-11-22. +// + +#pragma once +#include "ConjureEngine/ConjureEngine.h" + +namespace Demo1 { + +class Demo1: public ConjureEngine::Application { + public: + Demo1(); + int Run() const override; + void Tick(double deltaTime) const override; +}; + +} // Demo1 \ No newline at end of file diff --git a/Demo1/src/main.cpp b/Demo1/src/main.cpp index 1acdc2d..c98f119 100644 --- a/Demo1/src/main.cpp +++ b/Demo1/src/main.cpp @@ -1,5 +1,8 @@ -#include "ConjureEngine/Engine.h" +#include "ConjureEngine/ConjureEngine.h" +#include "Demo1.h" int main(int argc, char** argv) { - return 0; + Demo1::Demo1 app; + + return app.Run(); } \ No newline at end of file