should prob put this on git sometime

This commit is contained in:
2026-01-03 01:48:40 +01:00
commit 1b8cc96164
52 changed files with 12002 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 3.21)
project(lightkeeper LANGUAGES CXX C)
set(GAME_SRC
src/main.cpp
src/Lightkeeper.cpp
)
add_executable(lightkeeper ${GAME_SRC})
set_target_properties(lightkeeper PROPERTIES
CXX_STANDARD 20
CXX_EXTENSIONS OFF
)
#target_add_extra_warnings(lightkeeper)
target_include_directories(lightkeeper PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include")
target_link_libraries(lightkeeper PRIVATE destrum::destrum)
#symlink_assets(lightkeeper)
set(LK_SHADER_SRC "${CMAKE_CURRENT_LIST_DIR}/assets_src/shaders")
set(LK_SHADER_OUT "${CMAKE_CURRENT_LIST_DIR}/assets_runtime/shaders")
include(../cmake/compile_shaders.cmake)
compile_glsl_to_spv(lightkeeper "${LK_SHADER_SRC}" "${LK_SHADER_OUT}" LK_SPV)
add_dependencies(lightkeeper lightkeeper_shaders)
set(ENGINE_ASSETS_SRC "${CMAKE_SOURCE_DIR}/destrum/assets_runtime")
set(GAME_ASSETS_SRC "${CMAKE_SOURCE_DIR}/lightkeeper/assets_runtime")
set(ENGINE_ASSETS_DST "$<TARGET_FILE_DIR:lightkeeper>/assets/engine")
set(GAME_ASSETS_DST "$<TARGET_FILE_DIR:lightkeeper>/assets/game")
add_custom_command(TARGET lightkeeper POST_BUILD
# ensure parent dir exists
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:lightkeeper>/assets"
# remove destinations if they already exist (dir OR symlink)
COMMAND ${CMAKE_COMMAND} -E rm -rf "${ENGINE_ASSETS_DST}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${GAME_ASSETS_DST}"
# create symlinks
COMMAND ${CMAKE_COMMAND} -E create_symlink "${ENGINE_ASSETS_SRC}" "${ENGINE_ASSETS_DST}"
COMMAND ${CMAKE_COMMAND} -E create_symlink "${GAME_ASSETS_SRC}" "${GAME_ASSETS_DST}"
VERBATIM
)

View File

View File

@@ -0,0 +1,13 @@
#ifndef LIGHTKEEPER_H
#define LIGHTKEEPER_H
#include <destrum/App.h>
class LightKeeper : public App {
public:
LightKeeper();
};
#endif //LIGHTKEEPER_H

View File

@@ -0,0 +1,5 @@
#include "Lightkeeper.h"
LightKeeper::LightKeeper() {
}

29
lightkeeper/src/main.cpp Normal file
View File

@@ -0,0 +1,29 @@
#include <cstdio>
#include <SDL.h>
#include "Lightkeeper.h"
#include "spdlog/spdlog.h"
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", SDL_GetError(), nullptr);
return 1;
}
std::filesystem::path exeDir = SDL_GetBasePath();
spdlog::set_level(spdlog::level::debug);
LightKeeper app;
app.init({
.windowSize = {800, 600},
.renderSize = {800, 600},
.appName = "Astro Engine",
.windowTitle = "Lightkeeper",
.exeDir = exeDir,
});
app.run();
SDL_Quit();
return 0;
}

213
lightkeeper/src/main12.cpp Normal file
View File

@@ -0,0 +1,213 @@
#include <SDL.h>
#include <SDL_vulkan.h>
#include <vulkan/vulkan.h>
#include <VkBootstrap.h>
#include <vk_mem_alloc.h>
#include <vector>
#include <iostream>
#include <stdexcept>
#include <volk.h>
const int MAX_FRAMES_IN_FLIGHT = 2;
struct FrameData {
VkSemaphore imageAvailable;
VkSemaphore renderFinished;
VkFence inFlight;
VkCommandBuffer commandBuffer;
};
SDL_Window* window = nullptr;
VkInstance instance;
vkb::PhysicalDevice physicalDevice;
VkDevice device;
vkb::Device vkbDevice;
VkQueue graphicsQueue;
VkQueue presentQueue;
VkSurfaceKHR surface;
VkSwapchainKHR swapchain;
std::vector<VkImage> swapchainImages;
std::vector<VkImageView> swapchainImageViews;
VkCommandPool commandPool;
FrameData frames[MAX_FRAMES_IN_FLIGHT];
std::vector<VkFence> imagesInFlight;
size_t currentFrame = 0;
VkFormat swapchainImageFormat;
VkExtent2D swapchainExtent;
// --- Helper: allocate command buffer ---
VkCommandBuffer allocateCommandBuffer(VkDevice device, VkCommandPool pool) {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = pool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
VkCommandBuffer cmd;
vkAllocateCommandBuffers(device, &allocInfo, &cmd);
return cmd;
}
// --- Helper: record command buffer with dynamic rendering ---
void recordCommandBuffer(VkCommandBuffer cmd, VkImage image) {
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(cmd, &beginInfo);
VkRenderingAttachmentInfo colorAttachment{};
colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
colorAttachment.imageView = VK_NULL_HANDLE; // placeholder, normally swapchainImageViews[i]
colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkClearValue clearColor{ {{0.1f, 0.2f, 0.3f, 1.0f}} };
colorAttachment.clearValue = clearColor;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
VkRenderingInfo renderingInfo{};
renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
renderingInfo.renderArea.offset = {0, 0};
renderingInfo.renderArea.extent = {800, 600};
renderingInfo.layerCount = 1;
renderingInfo.colorAttachmentCount = 1;
renderingInfo.pColorAttachments = &colorAttachment;
vkCmdBeginRendering(cmd, &renderingInfo);
// No draw calls, just clear
vkCmdEndRendering(cmd);
vkEndCommandBuffer(cmd);
}
int SDL_main(int argc, char* argv[]) {
// --- SDL Window ---
if (SDL_Init(SDL_INIT_VIDEO) != 0)
throw std::runtime_error("SDL_Init failed");
window = SDL_CreateWindow("Vulkan SDL Dynamic Rendering",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 600,
SDL_WINDOW_VULKAN);
// --- Vulkan instance ---
volkInitialize();
vkb::InstanceBuilder builder;
auto instRet = builder.set_app_name("SDL Dynamic Rendering")
.request_validation_layers(true)
.build();
if (!instRet) throw std::runtime_error("Failed to create instance");
instance = instRet.value().instance;
if (!SDL_Vulkan_CreateSurface(window, instance, &surface))
throw std::runtime_error("Failed to create Vulkan surface");
// --- Physical device & logical device ---
vkb::PhysicalDeviceSelector selector{instRet.value()};
auto physRet = selector.set_minimum_version(1,2).set_surface(surface).require_dedicated_transfer_queue().select();
if (!physRet) throw std::runtime_error("Failed to select physical device");
physicalDevice = physRet.value();
vkb::DeviceBuilder deviceBuilder{physicalDevice};
auto devRet = deviceBuilder.build();
if (!devRet) throw std::runtime_error("Failed to create device");
device = devRet.value().device;
vkbDevice = devRet.value();
graphicsQueue = devRet.value().get_queue(vkb::QueueType::graphics).value();
presentQueue = devRet.value().get_queue(vkb::QueueType::present).value();
// --- Swapchain ---
vkb::SwapchainBuilder swapchainBuilder{vkbDevice};
auto swapRet = swapchainBuilder.set_desired_format(VkSurfaceFormatKHR{
.format = VK_FORMAT_B8G8R8A8_SRGB,
.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
})
.set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR)
.set_desired_extent(800,600)
.build();
if (!swapRet) throw std::runtime_error("Failed to create swapchain");
swapchain = swapRet.value().swapchain;
swapchainImages = swapRet.value().get_images().value();
swapchainImageFormat = swapRet.value().image_format;
swapchainExtent = swapRet.value().extent;
// --- Command pool ---
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = vkbDevice.get_queue_index(vkb::QueueType::graphics).value();
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool);
// --- Frames ---
imagesInFlight.resize(swapchainImages.size(), VK_NULL_HANDLE);
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
VkSemaphoreCreateInfo semInfo{};
semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vkCreateSemaphore(device, &semInfo, nullptr, &frames[i].imageAvailable);
vkCreateSemaphore(device, &semInfo, nullptr, &frames[i].renderFinished);
VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
vkCreateFence(device, &fenceInfo, nullptr, &frames[i].inFlight);
frames[i].commandBuffer = allocateCommandBuffer(device, commandPool);
}
// --- Main loop ---
bool running = true;
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) running = false;
}
FrameData& frame = frames[currentFrame];
vkWaitForFences(device, 1, &frame.inFlight, VK_TRUE, UINT64_MAX);
uint32_t imageIndex;
vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, frame.imageAvailable, VK_NULL_HANDLE, &imageIndex);
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE)
vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
imagesInFlight[imageIndex] = frame.inFlight;
vkResetFences(device, 1, &frame.inFlight);
vkResetCommandBuffer(frame.commandBuffer, 0);
recordCommandBuffer(frame.commandBuffer, swapchainImages[imageIndex]);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { frame.imageAvailable };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &frame.commandBuffer;
VkSemaphore signalSemaphores[] = { frame.renderFinished };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkQueueSubmit(graphicsQueue, 1, &submitInfo, frame.inFlight);
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapchain;
presentInfo.pImageIndices = &imageIndex;
vkQueuePresentKHR(presentQueue, &presentInfo);
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
vkDeviceWaitIdle(device);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}