CONGE-2 added the basic setup to open a windows on mac and windows

This commit is contained in:
Jimmy Tremblay-Bernier 2024-11-22 11:17:46 -05:00
parent dccbcf3cca
commit f64bb01ab2
17 changed files with 320 additions and 133 deletions

View File

@ -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
)

View File

@ -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

View File

@ -5,4 +5,10 @@
#include "Application.h"
namespace ConjureEngine {
} // ConjureEngine
Application::Application(const ApplicationInfo &applicationInfo): m_applicationInfo(applicationInfo) {
}
int Application::Run() const { return 0; }
void Application::Tick(double deltaTime) const {}
} // ConjureEngine

View File

@ -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
virtual void Tick(double deltaTime) const;
protected:
public:
protected:
ApplicationInfo m_applicationInfo;
};
} // ConjureEngine

View File

@ -0,0 +1,4 @@
#pragma once
#include "Application.h"
#include "Window.h"

View File

@ -1,4 +0,0 @@
//
// Created by Jimmy Tremblay-bernier on 2024-11-14.
//
#include "Engine.h"

View File

@ -1,7 +0,0 @@
#pragma once
#include "glm/glm.hpp"
namespace ConjureEngine {
}

View File

@ -18,4 +18,8 @@
#include "SDL2/SDL_video.h"
// VULKAN
#include "Vulkan/vulkan.h"
#include "vulkan/vulkan.h"
#include "vulkan/vulkan_core.h"
#ifdef __APPLE__
#include "vulkan/vulkan_metal.h"
#endif

View File

@ -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<VkPhysicalDevice>(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<VkQueueFamilyProperties> 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<uint32_t>(this->m_extensionNames.size());
vulkanInfos.ppEnabledExtensionNames = this->m_extensionNames.data();
}
VulkanContext::~VulkanContext() {
vkDestroyDevice(m_device, nullptr);
vkDestroyInstance(m_vkInst, nullptr);
}
} // ConjureEngine

View File

@ -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<const char*> m_extensionNames;
VkInstance m_vkInst{};
uint32_t m_physicalDeviceCount{0};
std::vector<VkPhysicalDevice> 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

View File

@ -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_Window>(
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<VkPhysicalDevice>(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<VkQueueFamilyProperties> 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

View File

@ -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<SDL_Window>& GetWindow() const;
const std::shared_ptr<VulkanContext>& GetVulkanContext() const;
private:
public:
private:
std::shared_ptr<SDL_Window> m_window;
uint32_t m_extensionCount{0};
const char** m_extensionNames{nullptr};
VkInstance m_vkInst;
uint32_t m_physicalDeviceCount{0};
std::vector<VkPhysicalDevice> m_physicalDevices;
SDL_Window* m_window;
VulkanContext* m_vulkanContext;
};
} // ConjureEngine

View File

@ -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)

42
Demo1/src/Demo1.cpp Normal file
View File

@ -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

17
Demo1/src/Demo1.h Normal file
View File

@ -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

View File

@ -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();
}