Added a descriptor set builder, changed some filepaths and added a basic server

This commit is contained in:
Alexandre 2026-05-24 13:13:20 +02:00
parent d3cc173d97
commit 921832a950
12 changed files with 407 additions and 48 deletions

View File

@ -7,3 +7,6 @@ CompileFlags:
- -DPIPELINES_IMPL - -DPIPELINES_IMPL
- -DDESCRIPTORS_IMPL - -DDESCRIPTORS_IMPL
- -DTIMER_IMPL - -DTIMER_IMPL
- -DLOGGER_IMPL
- -DSERVER_INIT_IMPL
- -DSERVER_IMPL

40
src/Common/Logger.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef LOGGER_H
#define LOGGER_H
// Custom includes
class NetLogger {
public:
struct Server{
int priority;
char* url[]; // Put the url at the end for bit optimization
};
void initNetLogger(Server server);
void logNet(char* body[], char* head, Server server);
void logNetAsync(); // Todo
private:
};
#endif // End of header
#ifdef LOGGER_IMPL
#ifndef LOGGER_IMPL_H
#define LOGGER_IMPL_H
// Implementation
// Includes
#include <httplib.h> // Todo : add it in the flake
void NetLogger::initNetLogger(Server server) {
httplib::Client cli(server.url)
// Todo : add error handling
}
#endif
#endif

View File

@ -32,6 +32,7 @@ void RunTimer::startTimer(){
} }
int RunTimer::endTimer() { int RunTimer::endTimer() {
endTime = Clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime); auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(endTime - startTime);
return elapsed.count(); return elapsed.count();
} }

View File

@ -28,7 +28,18 @@
// Custom headers // Custom headers
//#include "callbacks.h" //#include "callbacks.h"
#include "timer.h" #include "Timer.h"
#include "Logger.h"
// Custom macro
#define VK_CHECK(x) \
do { \
VkResult err = x; \
if (err) { \
fmt::println("[Engine:Error] Vulkan error : {}", string_VkResult(err)); \
abort(); \
} \
} while (0) \
// Custom types // Custom types

View File

@ -2,7 +2,7 @@
#define CALLBACK_H #define CALLBACK_H
// Header // Header
// Other includes // Other includes
#include "Common/types.h" #include "Common/Types.h"
class Callback { class Callback {
public: public:

View File

@ -2,7 +2,11 @@
#define DESCRIPTORS_H #define DESCRIPTORS_H
// Header // Header
// Other includes // Other includes
#include "Common/types.h" #include "Common/Types.h"
#include <cstdint>
#include <fmt/base.h>
#include <span>
#include <vulkan/vulkan_core.h>
struct DescriptorLayoutBuilder { struct DescriptorLayoutBuilder {
@ -23,6 +27,35 @@ struct DescriptorLayoutBuilder {
); );
}; };
struct DescriptorAllocator {
struct PoolSizeRatio {
VkDescriptorType type;
float ratio;
};
VkDescriptorPool pool;
void initPool(
VkDevice device,
uint32_t maxSets,
std::span<PoolSizeRatio> poolRatios
);
void clearDescriptors(
VkDevice device
);
void destroyPool(
VkDevice device
);
VkDescriptorSet allocate(
VkDevice device,
VkDescriptorSetLayout layout
);
};
#endif #endif
#ifdef DESCRIPTORS_IMPL #ifdef DESCRIPTORS_IMPL
@ -35,7 +68,7 @@ void DescriptorLayoutBuilder::addBinding(
VkDescriptorType type VkDescriptorType type
){ ){
#ifdef DEBUG #ifdef DEBUG
fmt::println("Adding a descriptor set binding..."); fmt::println("[DescriptorLayoutBuilder] Adding a descriptor set binding...");
#endif #endif
VkDescriptorSetLayoutBinding newBind { VkDescriptorSetLayoutBinding newBind {
.binding = binding, .binding = binding,
@ -44,26 +77,31 @@ void DescriptorLayoutBuilder::addBinding(
}; };
bindings.push_back(newBind); bindings.push_back(newBind);
#ifdef DEBUG
fmt::println("[DescriptorLayoutBuilder] Descriptor set binding added !");
#endif
} }
void DescriptorLayoutBuilder::clear() { void DescriptorLayoutBuilder::clear() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Clearing a descriptor set..."); fmt::println("[DescriptorLayoutBuilder] Clearing a descriptor set...");
#endif #endif
bindings.clear(); bindings.clear();
#ifdef DEBUG
fmt::println("[DescriptorLayoutBuilder] Descriptor set cleared !");
#endif
} }
VkDescriptorSetLayout DescriptorLayoutBuilder::build ( VkDescriptorSetLayout DescriptorLayoutBuilder::build (
VkDevice device, VkDevice device,
VkShaderStageFlags shaderStages, VkShaderStageFlags shaderStages,
void* pNext = nullptr, void* pNext,
VkDescriptorSetLayoutCreateFlags flags = 0 VkDescriptorSetLayoutCreateFlags flags
) { ) {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Building a descriptor set..."); fmt::println("[DescriptorLayoutBuilder] Building a descriptor set...");
#endif #endif
for (auto& b : bindings) { for (auto& b : bindings) {
@ -79,7 +117,7 @@ VkDescriptorSetLayout DescriptorLayoutBuilder::build (
.pBindings = bindings.data(), .pBindings = bindings.data(),
}; };
VkDescriptorSet set; VkDescriptorSetLayout set;
VK_CHECK( VK_CHECK(
vkCreateDescriptorSetLayout( vkCreateDescriptorSetLayout(
@ -89,10 +127,106 @@ VkDescriptorSetLayout DescriptorLayoutBuilder::build (
&set &set
) )
); );
#ifdef DEBUG
fmt::println("[DescriptorLayoutBuilder] Descriptor set built !");
#endif
return set; return set;
} }
void DescriptorAllocator::initPool(
VkDevice device,
uint32_t maxSets,
std::span<PoolSizeRatio> poolRatios
) {
#ifdef DEBUG
fmt::println("[DescriptorAllocator] Initializing a new pool..");
#endif
std::vector<VkDescriptorPoolSize> poolSizes;
for (PoolSizeRatio ratio : poolRatios) {
poolSizes.push_back(VkDescriptorPoolSize {
.type = ratio.type,
.descriptorCount = uint32_t(ratio.ratio * maxSets)
});
}
VkDescriptorPoolCreateInfo poolInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = 0,
.maxSets = maxSets,
.poolSizeCount = (uint32_t)poolSizes.size(),
.pPoolSizes = poolSizes.data()
};
vkCreateDescriptorPool(
device,
&poolInfo,
nullptr,
&pool
);
#ifdef DEBUG
fmt::println("[DescriptorAllocator] Descriptor pool initialized...");
#endif
}
void DescriptorAllocator::clearDescriptors(
VkDevice device
) {
#ifdef DEBUG
fmt::println("[DescriptorAllocator] Clearing a descriptor set...");
#endif
vkResetDescriptorPool(
device,
pool,
0
);
#ifdef DEBUG
fmt::println("[DescriptorAllocator] Descriptor set cleared !");
#endif
}
void DescriptorAllocator::destroyPool(
VkDevice device
) {
#ifdef DEBUG
fmt::println("[DescriptorAllocator] Destroying a descriptor pool...");
#endif
vkDestroyDescriptorPool(
device,
pool,
nullptr
);
#ifdef DEBUG
fmt::println("[DescriptorAllocator] Descriptor pool destroyed !");
#endif
}
VkDescriptorSet DescriptorAllocator::allocate(
VkDevice device,
VkDescriptorSetLayout layout
){
VkDescriptorSetAllocateInfo allocInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.pNext = nullptr,
.descriptorPool = pool,
.descriptorSetCount = 1,
.pSetLayouts = &layout
};
VkDescriptorSet ds;
VK_CHECK(
vkAllocateDescriptorSets(
device,
&allocInfo,
&ds
)
);
return ds;
}
#endif #endif
#endif #endif

View File

@ -2,8 +2,10 @@
#define ENGINE_H #define ENGINE_H
// Normal header // Normal header
#include "Common/types.h"
#include "descriptors.h" // Required for public interface custom allocator
#include "Common/Types.h"
#include <vulkan/vulkan_core.h>
struct FrameData { struct FrameData {
@ -55,6 +57,11 @@ class Engine {
AllocatedImage _drawImage; AllocatedImage _drawImage;
VkExtent2D _drawExtent; VkExtent2D _drawExtent;
// Descriptor Sets
DescriptorAllocator globalDescriptorAllocator;
VkDescriptorSet _drawImageDescriptors;
VkDescriptorSetLayout _drawImageDescriptorLayout;
void init(); void init();
@ -79,6 +86,8 @@ class Engine {
void drawBackground( void drawBackground(
VkCommandBuffer cmd VkCommandBuffer cmd
); );
void initDescriptors();
}; };
#endif #endif
@ -91,16 +100,19 @@ class Engine {
// Implementation defines // Implementation defines
#define IMAGES_IMPL #define IMAGES_IMPL
#define INITIALIZERS_IMPL #define INITIALIZERS_IMPL
#define DESCRIPTORS_IMPL
#define CALLBACK_IMPL #define CALLBACK_IMPL
#define TIMER_IMPL #define TIMER_IMPL
#define TYPES_IMPL
#define VMA_IMPLEMENTATION #define VMA_IMPLEMENTATION
// Custom includes // Custom includes
#include "images.h" #include "images.h"
#include "initializers.h" #include "initializers.h"
#include "callbacks.h" #include "callbacks.h"
#include "Common/timer.h" #include "descriptors.h"
#include "Common/types.h" #include "Common/Types.h"
#include "Common/Timer.h"
#include "VkBootstrap.h" #include "VkBootstrap.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
@ -115,20 +127,24 @@ constexpr bool bUseValidationLayers = true;
// Abort when there is an error // Abort when there is an error
// Todo : Give an error message or crash dump // Todo : Give an error message or crash dump
using namespace std; //using namespace std;
#define VK_CHECK(x) \ //#define VK_CHECK(x) \
do { \ do { \
VkResult err = x; \ VkResult err = x; \
if (err) { \ // if (err) { \
fmt::println("Vulkan error : {}", string_VkResult(err)); \ // fmt::println("[Engine:Error] Vulkan error : {}", string_VkResult(err)); \
abort(); \ // abort(); \
} \ // } \
} while (0) \ // } while (0) \
//======================
//=== Main Functions ===
//======================
void Engine::init() { void Engine::init() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Initializing the engine..."); fmt::println("[Engine:Init] Initializing the engine...");
fmt::println("Current engine version {}", BUILD_ID); fmt::println("[Engine:Info] Current engine version {}", BUILD_ID);
#endif #endif
glfwInit(); glfwInit();
@ -146,18 +162,18 @@ void Engine::init() {
glfwSetKeyCallback(window, Callback::keyboardCallback); glfwSetKeyCallback(window, Callback::keyboardCallback);
_isInitialized = true;
initRender(); initRender();
_isInitialized = true;
#ifdef DEBUG #ifdef DEBUG
fmt::println("Engine Initialized !"); fmt::println("[Engine:Init] Engine Initialized !");
#endif #endif
} }
void Engine::cleanup() { void Engine::cleanup() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Cleaning up..."); fmt::println("[Engine:Cleanup] Cleaning up...");
#endif #endif
if (_isInitialized) { if (_isInitialized) {
// Wait for the GPU to stop working // Wait for the GPU to stop working
@ -209,7 +225,7 @@ void Engine::cleanup() {
} }
#ifdef DEBUG #ifdef DEBUG
fmt::println("Engine cleaned up !"); fmt::println("[Engine:Cleanup] Engine cleaned up !");
#endif #endif
} }
@ -313,7 +329,7 @@ void Engine::draw() {
void Engine::run() { void Engine::run() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Running..."); fmt::println("[Engine:Info] Running...");
RunTimer timer; RunTimer timer;
timer.startTimer(); timer.startTimer();
#endif #endif
@ -337,10 +353,14 @@ void Engine::run() {
draw(); draw();
} }
#ifdef DEBUG #ifdef DEBUG
fmt::println("Engine has finished running after {} seconds!", timer.endTimer()); fmt::println("[Engine:Info] Engine has finished running after {} seconds!", timer.endTimer());
#endif #endif
} }
//======================
//=== Init Functions ===
//======================
void Engine::initRender() { void Engine::initRender() {
initVulkan(); initVulkan();
initSwapchain(); initSwapchain();
@ -348,11 +368,12 @@ void Engine::initRender() {
//initFramebuffers(); //initFramebuffers();
initCommands(); initCommands();
initSyncStructures(); initSyncStructures();
initDescriptors();
} }
void Engine::initVulkan() { void Engine::initVulkan() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Initializing Vulkan..."); fmt::println("[Engine:Init] Initializing Vulkan...");
#endif #endif
vkb::InstanceBuilder builder; vkb::InstanceBuilder builder;
@ -371,7 +392,7 @@ void Engine::initVulkan() {
// Create the surface // Create the surface
if (glfwCreateWindowSurface(_instance, window, nullptr, & _surface) != VK_SUCCESS) { if (glfwCreateWindowSurface(_instance, window, nullptr, & _surface) != VK_SUCCESS) {
throw std::runtime_error("Failed to create window surface !\nAborting..."); throw std::runtime_error("[Engine:Error] Failed to create window surface !\nAborting...");
} }
// Features // Features
@ -400,7 +421,7 @@ void Engine::initVulkan() {
vkb::DeviceBuilder deviceBuilder { physicalDevice }; vkb::DeviceBuilder deviceBuilder { physicalDevice };
#ifdef DEBUG #ifdef DEBUG
fmt::println("Device {}", physicalDevice.name); fmt::println("[Engine:Info] Device {}", physicalDevice.name);
#endif #endif
vkb::Device vkbDevice { deviceBuilder.build().value() }; vkb::Device vkbDevice { deviceBuilder.build().value() };
@ -423,13 +444,13 @@ void Engine::initVulkan() {
}); });
#ifdef DEBUG #ifdef DEBUG
fmt::println("Vulkan initialized !"); fmt::println("[Engine:Init] Vulkan initialized !");
#endif #endif
} }
void Engine::initSwapchain() { void Engine::initSwapchain() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Initializing the swapchain..."); fmt::println("[Engine:Init] Initializing the swapchain...");
#endif #endif
createSwapchain(_windowExtent.width, _windowExtent.height); createSwapchain(_windowExtent.width, _windowExtent.height);
@ -507,13 +528,13 @@ void Engine::initSwapchain() {
}); });
#ifdef DEBUG #ifdef DEBUG
fmt::println("Swapchain initialized !"); fmt::println("[Engine:Init] Swapchain initialized !");
#endif #endif
} }
void Engine::initCommands() { void Engine::initCommands() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Initializing vulkan commands.."); fmt::println("[Engine:Init] Initializing Vulkan commands..");
#endif #endif
VkCommandPoolCreateInfo commandPoolInfo = { VkCommandPoolCreateInfo commandPoolInfo = {
@ -544,13 +565,13 @@ void Engine::initCommands() {
); );
} }
#ifdef DEBUG #ifdef DEBUG
fmt::println("Vulan commands initialized !"); fmt::println("[Engine:Init] Vulkan commands initialized !");
#endif #endif
} }
void Engine::initSyncStructures() { void Engine::initSyncStructures() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Creating sync structures..."); fmt::println("[Engine:Init] Creating sync structures...");
#endif #endif
VkFenceCreateInfo fenceCreateInfo = vkinit::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); VkFenceCreateInfo fenceCreateInfo = vkinit::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT);
@ -564,16 +585,87 @@ void Engine::initSyncStructures() {
} }
#ifdef DEBUG #ifdef DEBUG
fmt::println("Sync structures created !"); fmt::println("[Engine:Init] Sync structures created !");
#endif #endif
} }
void Engine::initDescriptors(){
#ifdef DEBUG
fmt::println("[Engine:Init] Initializing descriptors...");
#endif
std::vector<DescriptorAllocator::PoolSizeRatio> sizes = {
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1 }
};
globalDescriptorAllocator.initPool(
_device,
10,
sizes
);
{
DescriptorLayoutBuilder builder;
builder.addBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
_drawImageDescriptorLayout = builder.build(
_device,
VK_SHADER_STAGE_COMPUTE_BIT
);
}
_drawImageDescriptors = globalDescriptorAllocator.allocate(
_device,
_drawImageDescriptorLayout
);
VkDescriptorImageInfo imgInfo {
.imageView = _drawImage.imageView,
.imageLayout = VK_IMAGE_LAYOUT_GENERAL
};
VkWriteDescriptorSet drawImageWrite = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.pNext = nullptr,
.dstSet = _drawImageDescriptors,
.dstBinding = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.pImageInfo = &imgInfo
};
vkUpdateDescriptorSets(
_device,
1,
&drawImageWrite,
0,
nullptr
);
_mainDeletionQueue.pushFunction([this]() {
globalDescriptorAllocator.destroyPool(_device);
vkDestroyDescriptorSetLayout(
_device,
_drawImageDescriptorLayout,
nullptr
);
});
#ifdef DEBUG
fmt::println("[Engine:Init] Descriptors initialized !");
#endif
}
//================================
//=== Render-related Functions ===
//================================
void Engine::createSwapchain( void Engine::createSwapchain(
uint32_t width, uint32_t width,
uint32_t height uint32_t height
) { ) {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Creating the Swapchain..."); fmt::println("[Engine:Init] Creating the Swapchain...");
#endif #endif
vkb::SwapchainBuilder swapchainBuilder { vkb::SwapchainBuilder swapchainBuilder {
_choosenGPU, _choosenGPU,
@ -603,13 +695,13 @@ void Engine::createSwapchain(
_swapchainImageViews = { vkbSwapchain.get_image_views().value() }; _swapchainImageViews = { vkbSwapchain.get_image_views().value() };
#ifdef DEBUG #ifdef DEBUG
fmt::println("Swapchain created with dimentions {} by {}", vkbSwapchain.extent.width, vkbSwapchain.extent.height); fmt::println("[Engine:Info] Swapchain created with dimentions {} by {}", vkbSwapchain.extent.width, vkbSwapchain.extent.height);
#endif #endif
} }
void Engine::destroySwapchain() { void Engine::destroySwapchain() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("Destroying the swapchain..."); fmt::println("[Engine:Cleanup] Destroying the swapchain...");
#endif #endif
vkDestroySwapchainKHR(_device, _swapchain, nullptr); vkDestroySwapchainKHR(_device, _swapchain, nullptr);
@ -618,7 +710,7 @@ void Engine::destroySwapchain() {
} }
#ifdef DEBUG #ifdef DEBUG
fmt::println("Swapchain destroyed !"); fmt::println("[Engine:Cleanup]Swapchain destroyed !");
#endif #endif
} }

View File

@ -1,7 +1,7 @@
#ifndef IMAGES_H #ifndef IMAGES_H
#define IMAGES_H #define IMAGES_H
// Normal header // Normal header
#include "Common/types.h" #include "Common/Types.h"
namespace vkutil { namespace vkutil {
void transitionImage( void transitionImage(

View File

@ -1,7 +1,7 @@
#ifndef INITIALIZERS_H #ifndef INITIALIZERS_H
#define INITIALIZERS_H #define INITIALIZERS_H
// Normal header // Normal header
#include "Common/types.h" #include "Common/Types.h"
namespace vkinit { namespace vkinit {
VkCommandPoolCreateInfo commandPoolCreateInfo( VkCommandPoolCreateInfo commandPoolCreateInfo(

View File

@ -1,3 +1,10 @@
#define SERVER_IMPL
#include "server/server.h"
int main() { int main() {
GameServer mainServer;
mainServer.init();
return 0; return 0;
} }

43
src/Server/server/init.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef SERVER_INIT_H
#define SERVER_INIT_H
// Normal header
class GameServerInit {
// This class groups all the code required for
// the server to initialize and start being
// usable
public:
bool init(); // Uses a bool to mark if init was sucessfull
void cleanup();
private:
};
#endif
#ifdef SERVER_INIT_IMPL
#ifndef SERVER_INIT_IMPL_H
#define SERVER_INIT_IMPL_H
// Implementation
#include "Common/Types.h"
bool GameServerInit::init() {
// Create the logger server object,
// to send messages
// Try to compile but I don't think it'll work in the current state
NetLogger::Server logServer {
.priority = 1,
.url = "https://ntfy.alexdelcamp.fr"
// clangd gives an error, fix it using the corrext type ig
// Todo : read the server from a file and fallback to my own
};
NetLogger::initNetLogger(logServer);
// Add error detection (no connectivity for exemple)
return true; // Everything went correctly
}
#endif
#endif

View File

@ -0,0 +1,28 @@
#ifndef SERVER_H
#define SERVER_H
// Normal header
class GameServer {
public:
void init(); // Wrapper to the init function in the init class
void cleanup(); // Wrapper to the cleanup function in the init class
private:
};
#endif
#ifdef SERVER_IMPL
#ifndef SERVER_IMPL_H
#define SERVER_IMPL_H
// Implementation
#include "init.h"
void GameServer::init(){
//GameServerInit::init();
}
#endif
#endif