diff --git a/CMakeLists.txt b/CMakeLists.txt index b98fbc4..f986290 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,10 +4,10 @@ cmake_minimum_required( VERSION 3.13 ) project( Aster VERSION 0.1.0 ) -set( CMAKE_CXX_STANDARD 20 ) +set( CMAKE_CXX_STANDARD 23 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_CXX_EXTENSIONS OFF ) - +set( CMAKE_CXX_FLAGS -Wall ) add_subdirectory( "aster_core" ) diff --git a/aster_core/CMakeLists.txt b/aster_core/CMakeLists.txt index cbf283d..42ad996 100644 --- a/aster_core/CMakeLists.txt +++ b/aster_core/CMakeLists.txt @@ -1,18 +1,25 @@ -# CMakeList.txt ; CMake project for Blaze +# CMakeList.txt ; CMake project for Aster Core cmake_minimum_required( VERSION 3.13 ) find_package( glm CONFIG REQUIRED ) +find_package( glfw3 CONFIG REQUIRED ) find_path( SCOTTT_DEBUGBREAK_INCLUDE_DIRS "debugbreak.h" ) -find_package( VulkanHeaders CONFIG REQUIRED ) +find_package( Vulkan REQUIRED ) +# find_package( VulkanHeaders CONFIG REQUIRED ) find_package( VulkanMemoryAllocator CONFIG REQUIRED ) -set( HEADER_FILES "constants.h" "config.h" "logger.h" "global.h" ) -set( SOURCE_FILES "logger.cpp" "global.cpp" ) +set( HEADER_FILES "constants.h" "config.h" "logger.h" "global.h" "context.h" "window.h" ) +set( SOURCE_FILES "logger.cpp" "global.cpp" "context.cpp" "window.cpp" ) -add_library( aster_core "aster.cpp" ${SOURCE_FILES} ${HEADER_FILES} ) -set_property( TARGET aster_core PROPERTY CXX_STANDARD 20 ) +add_library( aster_core ${SOURCE_FILES} ${HEADER_FILES} ) +set_property( TARGET aster_core PROPERTY CXX_STANDARD 23 ) target_link_libraries( aster_core PRIVATE glm::glm-header-only ) +target_link_libraries( aster_core PRIVATE glfw ) target_include_directories( aster_core PRIVATE ${SCOTTT_DEBUGBREAK_INCLUDE_DIRS}) -target_link_libraries( aster_core PRIVATE Vulkan::Headers GPUOpen::VulkanMemoryAllocator ) +target_link_libraries( aster_core PRIVATE Vulkan::Vulkan Vulkan::Headers GPUOpen::VulkanMemoryAllocator ) + +add_executable( aster_exe "aster.cpp" ) +target_link_libraries( aster_exe PRIVATE aster_core ) +target_link_libraries( aster_exe PRIVATE glm::glm-header-only ) diff --git a/aster_core/aster.cpp b/aster_core/aster.cpp index 780f4ec..b82f0b6 100644 --- a/aster_core/aster.cpp +++ b/aster_core/aster.cpp @@ -1,9 +1,17 @@ #include -#include +#include "constants.h" +#include "glfw_context.h" +#include "window.h" int main(int, char**) { - - printf("Hello World\n"); + + GlfwContext* glfw = new GlfwContext(); + Context* context = new Context("Aster", VERSION); + Window* window = new Window("Aster1", context, { 640, 480 }); + + delete window; + delete context; + delete glfw; return 0; } diff --git a/aster_core/constants.h b/aster_core/constants.h index 47f6b55..63d298d 100644 --- a/aster_core/constants.h +++ b/aster_core/constants.h @@ -30,7 +30,13 @@ using usize = size_t; using p64 = intptr_t; constexpr usize strlen_c(const char *s) { - return *s == '\0' ? 0 : 1 + strlen_c(s + 1); + usize len = 0; + char c = '\0'; + do { + c = s[len]; + len++; + } while (c != '\0'); + return len; } constexpr auto ANSI_Black = "\u001b[30m"; diff --git a/aster_core/glfw_context.h b/aster_core/glfw_context.h new file mode 100644 index 0000000..d251e1d --- /dev/null +++ b/aster_core/glfw_context.h @@ -0,0 +1,33 @@ +// ============================================= +// Aster: glfw_context.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +#include "global.h" + +struct GlfwContext { + static i32 post_error() noexcept { + static const char* error_ = nullptr; + const auto code = glfwGetError(&error_); + ERROR("GLFW "s + error_); + return code; + } + + inline static u32 count = 0; + + GlfwContext() { + if (count++ > 0) return; + if (glfwInit() == GLFW_FALSE) { + CRASH(post_error()); + } + } + + ~GlfwContext() { + if (--count == 0) { + glfwTerminate(); + } + count = 0; + } +}; diff --git a/aster_core/global.cpp b/aster_core/global.cpp index f348ee6..c5fad93 100644 --- a/aster_core/global.cpp +++ b/aster_core/global.cpp @@ -8,10 +8,8 @@ #include #include -#pragma warning(push, 0) #define VMA_IMPLEMENTATION #include -#pragma warning(pop) // NOTE: Vulkan Dispatch Loader Storage - Should only appear once. VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE diff --git a/aster_core/global.h b/aster_core/global.h index f621047..f1cf576 100644 --- a/aster_core/global.h +++ b/aster_core/global.h @@ -16,10 +16,7 @@ #define VULKAN_HPP_ASSERT(expr) DEBUG_IF(!(expr), "Vulkan assert failed") #include - -#pragma warning(push, 0) #include -#pragma warning(pop) #define CODE_LOC " @ " __FILE__ ":" VULKAN_HPP_STRINGIFY(__LINE__) [[nodiscard]] inline bool failed(const vk::Result _result) { diff --git a/aster_core/window.cpp b/aster_core/window.cpp new file mode 100644 index 0000000..2be78ec --- /dev/null +++ b/aster_core/window.cpp @@ -0,0 +1,78 @@ +// ============================================= +// Aster: window.cpp +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#include "window.h" +#include "logger.h" +#include "context.h" +#include "glfw_context.h" + +Window::Window(const std::string_view& _title, Context* _context, vk::Extent2D _extent, b8 _full_screen) + : parent_context{ std::move(_context) } + , extent{ _extent } + , name{ _title } + , full_screen{ _full_screen } { + + monitor = glfwGetPrimaryMonitor(); + ERROR_IF(monitor == nullptr, "No monitor found"); + + i32 x_, y_, w_, h_; + glfwGetMonitorWorkarea(monitor, &x_, &y_, &w_, &h_); + + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_TRUE); + + window = glfwCreateWindow(extent.width, extent.height, name.data(), full_screen ? monitor : nullptr, nullptr); + ERROR_IF(window == nullptr, "Window creation failed") ELSE_INFO(std::fmt("Window '%s' created with resolution '%dx%d'", name.data(), extent.width, extent.height)); + if (window == nullptr) { + auto code = GlfwContext::post_error(); + glfwTerminate(); + CRASH(code); + } + + if (full_screen == false) { + glfwSetWindowPos(window, (w_ - extent.width) / 2, (h_ - extent.height) / 2); + } + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + + VkSurfaceKHR surface_; + auto result = cast(glfwCreateWindowSurface(cast(_context->instance), window, nullptr, &surface_)); + ERROR_IF(failed(result), "Failed to create Surface with "s + to_string(result)) THEN_CRASH(result) ELSE_INFO("Surface Created"); + surface = vk::SurfaceKHR(surface_); +} + +Window::Window(Window&& _other) noexcept: parent_context{ std::move(_other.parent_context) } + , window{ std::exchange(_other.window, nullptr) } + , monitor{ _other.monitor } + , surface{ std::exchange(_other.surface, nullptr) } + , extent{ _other.extent } + , name{ std::move(_other.name) } + , full_screen{ _other.full_screen } {} + +Window& Window::operator=(Window&& _other) noexcept { + if (this == &_other) return *this; + parent_context = std::move(_other.parent_context); + window = _other.window; + monitor = _other.monitor; + surface = std::exchange(_other.surface, nullptr); + extent = _other.extent; + name = std::move(_other.name); + full_screen = _other.full_screen; + return *this; +} + +Window::~Window() { + if (parent_context && surface) { + parent_context->instance.destroy(surface); + INFO("Surface Destroyed"); + } + + if (window != nullptr) { + glfwDestroyWindow(window); + window = nullptr; + } + monitor = nullptr; + + INFO("Window '" + name + "' Destroyed"); +} diff --git a/aster_core/window.h b/aster_core/window.h new file mode 100644 index 0000000..e4929b7 --- /dev/null +++ b/aster_core/window.h @@ -0,0 +1,50 @@ +// ============================================= +// Aster: window.h +// Copyright (c) 2020-2024 Anish Bhobe +// ============================================= + +#pragma once + +#include "global.h" + +#include "context.h" + +struct Window final { + + Window(const std::string_view& _title, Context* _context, vk::Extent2D _extent, b8 _full_screen = false); + + Window(const Window& _other) = delete; + Window(Window&& _other) noexcept; + Window& operator=(const Window& _other) = delete; + Window& operator=(Window&& _other) noexcept; + + ~Window(); + + bool should_close() const noexcept { + return glfwWindowShouldClose(window); + } + + bool poll() const noexcept { + glfwPollEvents(); + return !glfwWindowShouldClose(window); + } + + void set_window_size(const vk::Extent2D& _extent) noexcept { + extent = _extent; + glfwSetWindowSize(window, extent.width, extent.height); + } + + void set_window_size(const u32 _width, const u32 _height) noexcept { + set_window_size({ _width, _height }); + } + + // fields + Context* parent_context{}; + + GLFWwindow* window{ nullptr }; + GLFWmonitor* monitor{ nullptr }; + vk::SurfaceKHR surface; + vk::Extent2D extent; + std::string name; + b8 full_screen{ false }; +}; diff --git a/run.sh b/run.sh index 8ede462..0d12c13 100755 --- a/run.sh +++ b/run.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash if [ -d "out" ]; then - pushd ./out/ > /dev/null || exit + pushd ./build/ > /dev/null || exit if echo "$@" | grep -e "debug" -q then lldb aster-exe