From 3c72fc91a5d8d15eca162d7aceab137b7075cf91 Mon Sep 17 00:00:00 2001 From: firewire Date: Sun, 12 Apr 2026 22:33:52 -0400 Subject: [PATCH] ctx - Instance creation --- CMakeLists.txt | 1 + examples/createContext/CMakeLists.txt | 18 ++++++ examples/createContext/main.cpp | 47 +++++++++++++++ examples/logging/CMakeLists.txt | 4 +- oatmeal/CMakeLists.txt | 1 + oatmeal/src/ctx.cpp | 2 +- oatmeal/src/ctx.h | 40 ++++++++++++- oatmeal/src/ctx_instance.cpp | 83 +++++++++++++++++++++++++++ 8 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 examples/createContext/CMakeLists.txt create mode 100644 examples/createContext/main.cpp create mode 100644 oatmeal/src/ctx_instance.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6176ffd..47b917d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,3 +30,4 @@ add_subdirectory(examples/shared) add_subdirectory(examples/basicGLFWWindow) add_subdirectory(examples/logging) +add_subdirectory(examples/createContext) diff --git a/examples/createContext/CMakeLists.txt b/examples/createContext/CMakeLists.txt new file mode 100644 index 0000000..a3e6d4f --- /dev/null +++ b/examples/createContext/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.28) +project(oatmeal) +set(CMAKE_CXX_STANDARD 23) + +add_executable(createContext "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp") +target_include_directories(createContext PRIVATE oatmeal SharedUtils) +target_link_libraries(createContext oatmeal SharedUtils) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set_target_properties(createContext PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/Debug/") +endif() +if(CMAKE_BUILD_TYPE STREQUAL "Release") + set_target_properties(createContext PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/Release/") +endif() +if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + set_target_properties(createContext PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/Relwithdeb/") +endif() + diff --git a/examples/createContext/main.cpp b/examples/createContext/main.cpp new file mode 100644 index 0000000..a8853a8 --- /dev/null +++ b/examples/createContext/main.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include "GLFW/glfw3.h" +#include "shared/logger.h" + +#include "ctx.h" + +int main() { + OatmealUtils::initLogging(); + OatmealUtils::createLogger("window", nullptr); + OatmealUtils::createLogger("context", nullptr); + + OatmealUtils::get("window")->info("Initializing GLFW"); + glfwInit(); + + OatmealUtils::get("window")->info("Setting window hints"); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + + OatmealUtils::get("window")->info("Create window"); + GLFWwindow *window = glfwCreateWindow(800, 600, "Oatmeal - Basic GLFW window", nullptr, nullptr); + if (window == nullptr) { + const char *desc; + uint32_t code = glfwGetError(&desc); + OatmealUtils::get("window")->critical("Failed to create window: ({}) {}", code, desc); + exit(EXIT_FAILURE); + } + + try { + Oatmeal::ctx ctx(window); + } catch (const std::exception &e) { + OatmealUtils::get("context")->critical("{}", e.what()); + return EXIT_FAILURE; + } + + + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + } + + OatmealUtils::get("window")->info("Cleaning up"); + glfwDestroyWindow(window); + glfwTerminate(); + + return 0; +} diff --git a/examples/logging/CMakeLists.txt b/examples/logging/CMakeLists.txt index e4d9196..fadeaf0 100644 --- a/examples/logging/CMakeLists.txt +++ b/examples/logging/CMakeLists.txt @@ -3,8 +3,8 @@ project(oatmeal) set(CMAKE_CXX_STANDARD 23) add_executable(logging "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp") -target_include_directories(logging PRIVATE oatmeal SharedUtils) -target_link_libraries(logging oatmeal SharedUtils) +target_include_directories(logging PRIVATE SharedUtils) +target_link_libraries(logging SharedUtils) if(CMAKE_BUILD_TYPE STREQUAL "Debug") set_target_properties(logging PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/Debug/") diff --git a/oatmeal/CMakeLists.txt b/oatmeal/CMakeLists.txt index 9cb89a1..e00119f 100644 --- a/oatmeal/CMakeLists.txt +++ b/oatmeal/CMakeLists.txt @@ -31,6 +31,7 @@ target_include_directories(oatmeal PUBLIC "${glm_SOURCE_DIR}" "${stb-cmake-wrapper_SOURCE_DIR}" "${ktx_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/src" ) target_link_libraries(oatmeal PUBLIC diff --git a/oatmeal/src/ctx.cpp b/oatmeal/src/ctx.cpp index 22e1d73..20662c2 100644 --- a/oatmeal/src/ctx.cpp +++ b/oatmeal/src/ctx.cpp @@ -2,7 +2,7 @@ #include namespace Oatmeal { - ctx::ctx(GLFWwindow *window, uint32_t width, uint32_t height) {} + ctx::ctx(GLFWwindow *window) { createInstance(); } ctx::~ctx() {} diff --git a/oatmeal/src/ctx.h b/oatmeal/src/ctx.h index f3fcf18..70e9209 100644 --- a/oatmeal/src/ctx.h +++ b/oatmeal/src/ctx.h @@ -1,3 +1,4 @@ +#include #include "vulkan/vulkan.hpp" #if defined(__INTELLISENSE__) || !defined(USE_CPP20_MODULES) #include @@ -39,9 +40,46 @@ namespace Oatmeal { class ctx { public: - ctx(GLFWwindow *window, uint32_t width, uint32_t height); + ctx(GLFWwindow *window); ~ctx(); private: + // Members // + + vk::raii::Context m_context; + vk::raii::Instance m_instance = nullptr; + vk::DebugUtilsMessengerEXT m_debugMessenger = nullptr; + vk::raii::PhysicalDevice m_physicalDevice = nullptr; + vk::raii::Device m_device = nullptr; + vk::raii::Queue m_queue = nullptr; + uint32_t m_queueIndex; + + vk::raii::SurfaceKHR m_surface = nullptr; + vk::raii::SwapchainKHR m_swapchain = nullptr; + std::vector m_swapchainImages; + vk::SurfaceFormatKHR m_swapchainSurfaceFormat; + vk::Extent2D m_swapchainExtent; + std::vector m_swapchainImageViews; + std::vector m_presentCompleteSemaphores; + std::vector m_renderFinishSemaphores; + std::vector m_inFlightFences; + bool m_framebufferResized = false; + uint32_t m_frameIndex = 0; + + vk::SampleCountFlagBits m_msaaSamples = vk::SampleCountFlagBits::e1; + vk::raii::Image m_colorImage = nullptr; + vk::raii::DeviceMemory m_colorImageMemory = nullptr; + vk::raii::ImageView m_colorImageView = nullptr; + + vk::raii::Image m_depthImage = nullptr; + vk::raii::DeviceMemory m_depthImageMemory = nullptr; + vk::raii::ImageView m_depthImageView = nullptr; + vk::Format m_depthFormat; + + // Functions // + + void createInstance(); + std::vector getRequiredExtensions(); + void setupDebugMessenger(); }; } // namespace Oatmeal diff --git a/oatmeal/src/ctx_instance.cpp b/oatmeal/src/ctx_instance.cpp new file mode 100644 index 0000000..1423786 --- /dev/null +++ b/oatmeal/src/ctx_instance.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include "ctx.h" +#include "vulkan/vulkan.hpp" + +namespace Oatmeal { + + void ctx::createInstance() { + // Create the application info + constexpr vk::ApplicationInfo appInfo{ + .pApplicationName = "Oatmeal", + .applicationVersion = VK_MAKE_VERSION(1, 0, 0), + .pEngineName = "No engine", + .engineVersion = VK_MAKE_API_VERSION(1, 0, 0, 0), + .apiVersion = vk::ApiVersion14, + }; + + // Loop through the required layers, making sure they are supported + std::vector requiredLayers; + if (enableValidationLayers) { + requiredLayers.assign(validationLayers.begin(), validationLayers.end()); + } + + auto layerProperties = m_context.enumerateInstanceLayerProperties(); + for (auto const &requiredLayer: requiredLayers) { + bool found = false; + for (auto const &layerProperty: layerProperties) { + if (strcmp(layerProperty.layerName, requiredLayer)) { + found = true; + } + } + if (!found) { + // TODO: Not sure i like throwing runtime errors, might need to find a better solution + throw std::runtime_error("Required layer not supported: " + std::string(requiredLayer)); + } + } + + // Loop through the required extensions, making sure they are supported + auto requiredExtensions = getRequiredExtensions(); + auto extensionProperties = m_context.enumerateInstanceExtensionProperties(); + for (auto const &requiredExtension: requiredExtensions) { + bool found = false; + for (auto const &extensionProperty: extensionProperties) { + if (strcmp(extensionProperty.extensionName, requiredExtension)) { + found = true; + } + } + if (!found) { + // TODO: Not sure i like just throwing a runtime error, might need to find a better solution for error + // handling + throw std::runtime_error("Required extension not found: " + std::string(requiredExtension)); + } + } + + + // Create the instance + vk::InstanceCreateInfo createInfo{ + .pApplicationInfo = &appInfo, + .enabledLayerCount = static_cast(requiredLayers.size()), + .ppEnabledLayerNames = requiredLayers.data(), + .enabledExtensionCount = static_cast(requiredExtensions.size()), + .ppEnabledExtensionNames = requiredExtensions.data(), + }; + + m_instance = vk::raii::Instance(m_context, createInfo); + } + + std::vector ctx::getRequiredExtensions() { + uint32_t glfwExtensionCount = 0; + auto glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + + if (enableValidationLayers) { + extensions.push_back(vk::EXTDebugUtilsExtensionName); + } + + return extensions; + } + +} // namespace Oatmeal