should prob put this on git sometime
This commit is contained in:
52
lightkeeper/CMakeLists.txt
Normal file
52
lightkeeper/CMakeLists.txt
Normal 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
|
||||
)
|
||||
0
lightkeeper/assets_src/temp
Normal file
0
lightkeeper/assets_src/temp
Normal file
13
lightkeeper/include/Lightkeeper.h
Normal file
13
lightkeeper/include/Lightkeeper.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef LIGHTKEEPER_H
|
||||
#define LIGHTKEEPER_H
|
||||
|
||||
#include <destrum/App.h>
|
||||
|
||||
class LightKeeper : public App {
|
||||
public:
|
||||
LightKeeper();
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //LIGHTKEEPER_H
|
||||
5
lightkeeper/src/Lightkeeper.cpp
Normal file
5
lightkeeper/src/Lightkeeper.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "Lightkeeper.h"
|
||||
|
||||
LightKeeper::LightKeeper() {
|
||||
|
||||
}
|
||||
29
lightkeeper/src/main.cpp
Normal file
29
lightkeeper/src/main.cpp
Normal 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
213
lightkeeper/src/main12.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user