Tweaked the flake, changed some logs

This commit is contained in:
Alexandre 2026-09-15 21:47:23 +02:00
parent 1ad367d650
commit 53a1a73bfc
5 changed files with 198 additions and 171 deletions

4
.envrc
View File

@ -1,3 +1 @@
FLAKEPATH="/home/alex/Developer/nix/NixOSDots/dev-flakes" use flake
use flake ${FLAKEPATH}/vulkan

View File

@ -74,7 +74,9 @@
shellHook = '' shellHook = ''
echo "Vulkan loaded" echo "Vulkan loaded"
echo "MangoHud version: $(mangohud --version 2>/dev/null || echo 'non trouvée')"
unset SOURCE_DATE_EPOCH unset SOURCE_DATE_EPOCH
#unset NIX_ENFORCE_NO_NATIVE
echo $LD_LIBRARY_PATH echo $LD_LIBRARY_PATH
''; '';
}; };

View File

@ -23,9 +23,11 @@
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#define GLM_ENABLE_EXPERIMENTAL
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_FORCE_RADIANS
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/transform.hpp> #include <glm/gtx/transform.hpp>
// Custom headers // Custom headers
@ -43,9 +45,16 @@
} \ } \
} while (0) \ } while (0) \
// Enums
enum class RenderRez {
FIT,
R800x800,
R720p,
R1080p,
R2k
};
// Custom types // Custom types
struct DeletionQueue { struct DeletionQueue {
std::deque<std::function<void()>> deletors; std::deque<std::function<void()>> deletors;
@ -80,6 +89,7 @@ struct AllocatedBuffer {
VkBuffer buffer; VkBuffer buffer;
VmaAllocation allocation; VmaAllocation allocation;
VmaAllocationInfo info; VmaAllocationInfo info;
uint32_t size; // In bytes
}; };
struct Vertex { struct Vertex {
@ -104,7 +114,8 @@ struct GPUDrawPushConstants {
// Engine config // Engine config
struct EngineConfig { struct EngineConfig {
int gpuIndex; int gpuIndex {-1};
std::string modelPath;
}; };
// "Global" ? (I hope so) logger // "Global" ? (I hope so) logger

View File

@ -3,7 +3,8 @@
// Normal header // Normal header
// Current progress // Current progress
// 3 - Graphics Pipeline - Doing depth image creation in swapchain init // 3 - Graphics Pipeline - Blending
// Currently rewriting render images
#include "descriptors.h" // Required for public interface custom allocator #include "descriptors.h" // Required for public interface custom allocator
#include "Common/Types.h" #include "Common/Types.h"
@ -46,12 +47,15 @@ class Engine {
public: public:
//========== Class Members ========== //========== Class Members ==========
// Config // Config
int _gpuIndex {-1}; // Unitialized EngineConfig _conf;
bool _isInitialized { false }; bool _isInitialized { false };
int _frameNumber { 0 }; int _frameNumber { 0 };
VkExtent2D _windowExtent; VkExtent2D _viewportPanelSize { 1, 1 };
VkExtent2D _windowExtent;
GLFWwindow *window { nullptr }; GLFWwindow *window { nullptr };
uint32_t _gpuMemusage;
// Vulkan specific class members // Vulkan specific class members
VkInstance _instance; VkInstance _instance;
@ -86,6 +90,7 @@ class Engine {
AllocatedImage _drawImage; AllocatedImage _drawImage;
AllocatedImage _depthImage; // Depth testing AllocatedImage _depthImage; // Depth testing
VkExtent2D _drawExtent; VkExtent2D _drawExtent;
float renderScale = 1.0f;
// Descriptor Sets // Descriptor Sets
DescriptorAllocator globalDescriptorAllocator; DescriptorAllocator globalDescriptorAllocator;
@ -103,7 +108,6 @@ class Engine {
// Resize // Resize
bool _requestResize; bool _requestResize;
bool _requestRez; // Resolution
// Push constants // Push constants
std::vector<ComputeEffect> backgroundEffects; std::vector<ComputeEffect> backgroundEffects;
@ -132,8 +136,7 @@ class Engine {
std::vector<std::shared_ptr<MeshAsset>> testMeshes; std::vector<std::shared_ptr<MeshAsset>> testMeshes;
void parseConfig( void parseConfig(
int gpuIndex, EngineConfig conf
std::string modelPath
); );
void init(); void init();
@ -203,10 +206,6 @@ class Engine {
VkImageView targetImageView VkImageView targetImageView
); );
void resizeSwapchain(); void resizeSwapchain();
void resizeRenderImage(
uint32_t width,
uint32_t height
);
}; };
#endif #endif
@ -277,16 +276,14 @@ constexpr bool bUseValidationLayers = false;
//====================== //======================
void Engine::parseConfig( void Engine::parseConfig(
int gpuIndex, EngineConfig conf
std::string modelPath
) { ) {
_gpuIndex = gpuIndex; _conf = conf;
if(!modelPath.size() == 0) { if(!conf.modelPath.size() == 0) {
#ifdef DEBUG #ifdef DEBUG
_logger.logAll(ENGINE, EINFO, "Model overwrite, using {}", modelPath); _logger.logAll(ENGINE, EINFO, "Model overwrite, using {}", conf.modelPath);
#endif #endif
_modelPath = modelPath;
} }
} }
@ -304,7 +301,7 @@ void Engine::init() {
#endif #endif
if(!glfwInit()) { if(!glfwInit()) {
throw std::runtime_error("Failed to init GLFW !"); _logger.logFatal(ENGINE, "Failed to init GLFW !");
} }
// Get primary monitor // Get primary monitor
@ -345,6 +342,7 @@ void Engine::init() {
void Engine::cleanup() { void Engine::cleanup() {
#ifdef DEBUG #ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Cleaning up..."); _logger.logConsole(CLEANUP, EINFO, "Cleaning up...");
_logger.logConsole(CLEANUP, EINFO, "Total mem usage {} Bytes", _gpuMemusage);
#endif #endif
if (_isInitialized) { if (_isInitialized) {
// Wait for the GPU to stop working // Wait for the GPU to stop working
@ -393,7 +391,7 @@ void Engine::draw() {
// wait until the gpu has finished rendering the last frame. Timeout of 1s // wait until the gpu has finished rendering the last frame. Timeout of 1s
VK_CHECK(vkWaitForFences(_device, 1, &getCurrentFrame()._renderFence, true, UINT64_MAX)); VK_CHECK(vkWaitForFences(_device, 1, &getCurrentFrame()._renderFence, true, UINT64_MAX));
// Flush frame data // Flush frame data
getCurrentFrame()._deletionQueue.flush(); getCurrentFrame()._deletionQueue.flush();
// Request image from the swapchain // Request image from the swapchain
@ -407,7 +405,7 @@ void Engine::draw() {
_requestResize = true; _requestResize = true;
return; return;
} else if (aquireResult != VK_SUCCESS) { } else if (aquireResult != VK_SUCCESS) {
throw std::runtime_error("Failed to aquire swapchain image"); _logger.logFatal(ENGINE, "Failed to aquire swapchain image");
} }
// Reset fences to redo sync // Reset fences to redo sync
@ -415,8 +413,8 @@ void Engine::draw() {
VkCommandBuffer cmd = getCurrentFrame()._mainCommandBuffer; VkCommandBuffer cmd = getCurrentFrame()._mainCommandBuffer;
_drawExtent.width = _drawImage.imageExtent.width; _drawExtent.width = std::min(_viewportPanelSize.width, _drawImage.imageExtent.width) * renderScale;
_drawExtent.height = _drawImage.imageExtent.height; _drawExtent.height = std::min(_viewportPanelSize.height, _drawImage.imageExtent.height) * renderScale;
VK_CHECK(vkResetCommandBuffer(cmd, 0)); VK_CHECK(vkResetCommandBuffer(cmd, 0));
@ -545,7 +543,7 @@ void Engine::draw() {
_requestResize = true; _requestResize = true;
return; return;
} else if (presentResult != VK_SUCCESS) { } else if (presentResult != VK_SUCCESS) {
throw std::runtime_error("Failed to present swapchain image"); _logger.logFatal(ENGINE, "Failed to present swapchain image");
} }
@ -553,6 +551,10 @@ void Engine::draw() {
} }
void Engine::run() { void Engine::run() {
// Todo, add frametime, and average
// Average buffer should have a fixed size,
// overwriting older values
// It should display at the end, alongside engine runtime
#ifdef DEBUG #ifdef DEBUG
_logger.logAll(ENGINE, EINFO,"Running..."); _logger.logAll(ENGINE, EINFO,"Running...");
RunTimer timer; RunTimer timer;
@ -596,7 +598,6 @@ void Engine::run() {
logger.clear(); logger.clear();
} }
#ifdef DEBUG #ifdef DEBUG
// Not an error but logs to required targets
_logger.logImportant(ENGINE, EINFO, "Engine has finished running after {} seconds!", timer.endTimer()); _logger.logImportant(ENGINE, EINFO, "Engine has finished running after {} seconds!", timer.endTimer());
#endif #endif
} }
@ -636,7 +637,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("[Engine:Error] Failed to create window surface !\nAborting..."); _logger.logFatal(ENGINE, "Failed to create window surface !\nAborting...");
} }
// Features // Features
@ -653,7 +654,7 @@ void Engine::initVulkan() {
.bufferDeviceAddress = true .bufferDeviceAddress = true
}; };
if(_gpuIndex < 0) { if(_conf.gpuIndex < 0) {
// No overwrite, use VKB // No overwrite, use VKB
// Use vkBootstrap to select the GPU // Use vkBootstrap to select the GPU
vkb::PhysicalDeviceSelector selector { vkbInst }; vkb::PhysicalDeviceSelector selector { vkbInst };
@ -680,30 +681,29 @@ void Engine::initVulkan() {
} else { } else {
// Overwrite, select GPU by hand // Overwrite, select GPU by hand
#ifdef DEBUG #ifdef DEBUG
_logger.logAll(ENGINE, EINFO, "Manual GPU selection, choose {}", _gpuIndex); _logger.logAll(ENGINE, EINFO, "Manual GPU selection, choose {}", _conf.gpuIndex);
#endif #endif
uint32_t deviceCount = 0; uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(_instance, &deviceCount, nullptr); vkEnumeratePhysicalDevices(_instance, &deviceCount, nullptr);
if (deviceCount == 0) { if (deviceCount == 0) {
throw std::runtime_error("[Engine:Error] No Vulkan GPU found !"); _logger.logFatal(ENGINE, "No Vulkan GPU found !");
} }
std::vector<VkPhysicalDevice> devices(deviceCount); std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(_instance, &deviceCount, devices.data()); vkEnumeratePhysicalDevices(_instance, &deviceCount, devices.data());
if (_gpuIndex >= deviceCount) { if (_conf.gpuIndex >= deviceCount) {
throw std::runtime_error( _logger.logFatal(
"[Engine:Error] GPU index " ENGINE,
+ std::to_string(_gpuIndex) "Invalid GPU index, there is {} available gpus (you selected {})",
+ " out of bounds !(" deviceCount,
+ std::to_string(deviceCount) _conf.gpuIndex
+ " available GPUs)"
); );
} }
_choosenGPU = devices[_gpuIndex]; _choosenGPU = devices[_conf.gpuIndex];
VkPhysicalDeviceProperties props{}; VkPhysicalDeviceProperties props{};
vkGetPhysicalDeviceProperties(_choosenGPU, &props); vkGetPhysicalDeviceProperties(_choosenGPU, &props);
@ -728,7 +728,7 @@ void Engine::initVulkan() {
} }
if (!queueFamily.has_value()) { if (!queueFamily.has_value()) {
throw std::runtime_error("[Engine:Error] No graphics queue compatible with the surface on the selected GPU !"); _logger.logFatal(ENGINE, "No graphics queue compatible with the surface on the selected GPU !");
} }
_graphicsQueueFamily = queueFamily.value(); _graphicsQueueFamily = queueFamily.value();
@ -759,7 +759,7 @@ void Engine::initVulkan() {
}; };
if (vkCreateDevice(_choosenGPU, &deviceCreateInfo, nullptr, &_device) != VK_SUCCESS) { if (vkCreateDevice(_choosenGPU, &deviceCreateInfo, nullptr, &_device) != VK_SUCCESS) {
throw std::runtime_error("[Engine:Error] Failed to create Vulkan device !"); _logger.logFatal(ENGINE, "Failed to create Vulkan device !");
} }
vkGetDeviceQueue(_device, _graphicsQueueFamily, 0, &_graphicsQueue); vkGetDeviceQueue(_device, _graphicsQueueFamily, 0, &_graphicsQueue);
@ -790,20 +790,27 @@ void Engine::initSwapchain() {
#ifdef DEBUG #ifdef DEBUG
_logger.logRAM(ENGINE, EINIT, "Initializing the swapchain..."); _logger.logRAM(ENGINE, EINIT, "Initializing the swapchain...");
#endif #endif
/*
glfwGetFramebufferSize( glfwGetFramebufferSize(
window, window,
(int*)&_windowExtent.width, (int*)&_windowExtent.width,
(int*)&_windowExtent.height (int*)&_windowExtent.height
); );
*/
createSwapchain(_windowExtent.width, _windowExtent.height); createSwapchain(_windowExtent.width, _windowExtent.height);
VkExtent3D drawImageExtent = { // Allocate the offscreen target once, at a big enough size
_windowExtent.width, // so we don't need to reallocate.
_windowExtent.height, const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
1 uint32_t maxW = mode ? mode->width : _windowExtent.width;
}; uint32_t maxH = mode ? mode->height : _windowExtent.height;
VkExtent3D drawImageExtent = { maxW, maxH, 1 };
// Seeds a drawExtent so frame 0 has something to render
// if ImGui isn't drawn yet
_drawExtent = { _windowExtent.width, _windowExtent.height };
// Hardcoding draw format to a 32 bit float // Hardcoding draw format to a 32 bit float
_drawImage.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT; _drawImage.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
@ -901,6 +908,9 @@ void Engine::initSwapchain() {
// Add to deletion queue // Add to deletion queue
_mainDeletionQueue.pushFunction([this]() { _mainDeletionQueue.pushFunction([this]() {
#ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Swapchain (draw images)");
#endif
// Draw image // Draw image
vkDestroyImageView( vkDestroyImageView(
_device, _device,
@ -928,6 +938,13 @@ void Engine::initSwapchain() {
#ifdef DEBUG #ifdef DEBUG
_logger.logRAM(ENGINE, EINIT, "Swapchain initialized !"); _logger.logRAM(ENGINE, EINIT, "Swapchain initialized !");
_logger.logRAM(
ENGINE,
EINFO,
"DrawImage dimensions {} x {}",
drawImageExtent.width,
drawImageExtent.height
);
#endif #endif
} }
@ -985,6 +1002,9 @@ void Engine::initCommands() {
); );
_mainDeletionQueue.pushFunction([this]() { _mainDeletionQueue.pushFunction([this]() {
#ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Command pools (immediate");
#endif
vkDestroyCommandPool( vkDestroyCommandPool(
_device, _device,
_immCommandPool, _immCommandPool,
@ -1040,6 +1060,9 @@ void Engine::initSyncStructures() {
); );
_syncDeletionQueue.pushFunction([this]() { _syncDeletionQueue.pushFunction([this]() {
#ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Sync structures (immediate fences)");
#endif
vkDestroyFence( vkDestroyFence(
_device, _device,
_immFence, _immFence,
@ -1048,13 +1071,13 @@ void Engine::initSyncStructures() {
}); });
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Init] Sync structures created !"); _logger.logRAM(ENGINE, EINIT, "Sync structures created !");
#endif #endif
} }
void Engine::initDescriptors(){ void Engine::initDescriptors(){
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Init] Initializing descriptors..."); _logger.logRAM(ENGINE, EINIT, "Initializing descriptors...");
#endif #endif
std::vector<DescriptorAllocator::PoolSizeRatio> sizes = { std::vector<DescriptorAllocator::PoolSizeRatio> sizes = {
@ -1105,6 +1128,9 @@ void Engine::initDescriptors(){
); );
_mainDeletionQueue.pushFunction([this]() { _mainDeletionQueue.pushFunction([this]() {
#ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Descriptors sets");
#endif
globalDescriptorAllocator.destroyPool(_device); globalDescriptorAllocator.destroyPool(_device);
vkDestroyDescriptorSetLayout( vkDestroyDescriptorSetLayout(
@ -1115,13 +1141,13 @@ void Engine::initDescriptors(){
}); });
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Init] Descriptors initialized !"); _logger.logRAM(ENGINE, EINIT, "Descriptors initialized !");
#endif #endif
} }
void Engine::initImgui() { void Engine::initImgui() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Init] Initializing ImGui..."); _logger.logRAM(ENGINE, EINIT, "Initializing ImGui...");
#endif #endif
// Oversized descriptor pool for IMGUI, from the official tutorial // Oversized descriptor pool for IMGUI, from the official tutorial
// Ajust for optimization, or needs // Ajust for optimization, or needs
@ -1196,6 +1222,8 @@ void Engine::initImgui() {
ImGui_ImplVulkan_Init(&initInfo); ImGui_ImplVulkan_Init(&initInfo);
// Create a sampler for Viewport rendering // Create a sampler for Viewport rendering
// Todo
// Conversion to structs
VkSamplerCreateInfo samplerInfo = {}; VkSamplerCreateInfo samplerInfo = {};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR; samplerInfo.magFilter = VK_FILTER_LINEAR;
@ -1217,6 +1245,9 @@ void Engine::initImgui() {
); );
_mainDeletionQueue.pushFunction([this, imguiPool]() { _mainDeletionQueue.pushFunction([this, imguiPool]() {
#ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Imgui");
#endif
ImGui_ImplVulkan_Shutdown(); ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown(); ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
@ -1232,7 +1263,7 @@ void Engine::initImgui() {
); );
}); });
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Init] ImGui initialized !"); _logger.logRAM(ENGINE, EINIT, "ImGui initialized !");
#endif #endif
} }
@ -1295,7 +1326,7 @@ void Engine::initBackgroundPipelines() {
&gradientShader &gradientShader
) )
) { ) {
fmt::println("[Engine:Error] Error when building the compute shader !"); _logger.logFatal(ENGINE, "Error when building the gradient compute shader !");
} }
// Create the second shader // Create the second shader
@ -1307,7 +1338,7 @@ void Engine::initBackgroundPipelines() {
&skyShader &skyShader
) )
) { ) {
fmt::println("[Engine:Error] Error while building the compute shader !"); _logger.logFatal(ENGINE, "Error when building the sky compute shader !");
} }
// Fist Shader // Fist Shader
@ -1386,6 +1417,9 @@ void Engine::initBackgroundPipelines() {
); );
_mainDeletionQueue.pushFunction([this, sky, gradient]() { _mainDeletionQueue.pushFunction([this, sky, gradient]() {
#ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Compute pipelines");
#endif
vkDestroyPipelineLayout( vkDestroyPipelineLayout(
_device, _device,
_gradientPipelineLayout, _gradientPipelineLayout,
@ -1416,7 +1450,7 @@ void Engine::initMeshPipeline() {
#endif #endif
VkShaderModule triangleFragShader; VkShaderModule triangleFragShader;
if (!vkutil::loadShaderModule("shaders/colored_triangle_fragment.spv", _device, &triangleFragShader)) { if (!vkutil::loadShaderModule("shaders/colored_triangle_fragment.spv", _device, &triangleFragShader)) {
fmt::println("[Engine:Error] Error when building the triangle fragment shader module"); _logger.logFatal(ENGINE, "Error when building the triangle fragment shader module");
} }
else { else {
_logger.logRAM(ENGINE, EINFO, "Triangle fragment shader succesfully loaded"); _logger.logRAM(ENGINE, EINFO, "Triangle fragment shader succesfully loaded");
@ -1424,7 +1458,7 @@ void Engine::initMeshPipeline() {
VkShaderModule triangleVertexShader; VkShaderModule triangleVertexShader;
if (!vkutil::loadShaderModule("shaders/colored_triangle_mesh.spv", _device, &triangleVertexShader)) { if (!vkutil::loadShaderModule("shaders/colored_triangle_mesh.spv", _device, &triangleVertexShader)) {
fmt::println("[Engine:Error] Error when building the triangle vertex shader module"); _logger.logFatal(ENGINE, "Error when building the triangle vertex shader module");
} }
else { else {
_logger.logRAM(ENGINE, EINFO, "Triangle vertex shader succesfully loaded"); _logger.logRAM(ENGINE, EINFO, "Triangle vertex shader succesfully loaded");
@ -1499,6 +1533,10 @@ AllocatedBuffer Engine::createBuffer(
VkBufferUsageFlags usage, VkBufferUsageFlags usage,
VmaMemoryUsage memoryUsage VmaMemoryUsage memoryUsage
) { ) {
#ifdef DEBUG
_logger.logRAM(ENGINE, EINIT, "Creating a buffer with memory usage {} KiB", (float)allocSize/1024.0f);
_gpuMemusage += allocSize;
#endif
// Allocate the buffer // Allocate the buffer
VkBufferCreateInfo bufferInfo { VkBufferCreateInfo bufferInfo {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
@ -1513,6 +1551,7 @@ AllocatedBuffer Engine::createBuffer(
}; };
AllocatedBuffer newBuffer; AllocatedBuffer newBuffer;
newBuffer.size = allocSize;
// Allocate the buffer // Allocate the buffer
VK_CHECK( VK_CHECK(
@ -1532,6 +1571,9 @@ AllocatedBuffer Engine::createBuffer(
void Engine::destroyBuffer( void Engine::destroyBuffer(
const AllocatedBuffer& buffer const AllocatedBuffer& buffer
) { ) {
#ifdef DEBUG
_gpuMemusage -= buffer.size;
#endif
vmaDestroyBuffer( vmaDestroyBuffer(
_allocator, _allocator,
buffer.buffer, buffer.buffer,
@ -1547,6 +1589,9 @@ GPUMeshBuffers Engine::uploadMesh(
std::span<uint32_t> indices, std::span<uint32_t> indices,
std::span<Vertex> vertices std::span<Vertex> vertices
) { ) {
#ifdef DEBUG
_logger.logRAM(ENGINE, EINFO, "Uploading mesh...");
#endif
const size_t vertexBufferSize = vertices.size() * sizeof(Vertex); const size_t vertexBufferSize = vertices.size() * sizeof(Vertex);
const size_t indexBufferSize = indices.size() * sizeof(uint32_t); const size_t indexBufferSize = indices.size() * sizeof(uint32_t);
@ -1642,10 +1687,44 @@ void Engine::initDefaultData() {
#ifdef DEBUG #ifdef DEBUG
_logger.logRAM(ENGINE, EINIT, "Creating default data..."); _logger.logRAM(ENGINE, EINIT, "Creating default data...");
#endif #endif
std::array<Vertex, 4> rectVertices;
rectVertices[0].position = {0.5, -0.5, 0};
rectVertices[1].position = {0.5, 0.5, 0};
rectVertices[2].position = {-0.5, -0.5, 0};
rectVertices[3].position = {-0.5, 0.5, 0};
rectVertices[0].color = {0, 0, 0, 1};
rectVertices[1].color = {0.5, 0.5, 0.5, 1};
rectVertices[2].color = {1, 0, 0, 1};
rectVertices[3].color = {0, 1, 0, 1};
std::array<uint32_t, 6> rectIndices;
rectIndices[0] = 0;
rectIndices[1] = 1;
rectIndices[2] = 2;
rectIndices[3] = 2;
rectIndices[4] = 1;
rectIndices[5] = 3;
rectangle = uploadMesh(
rectIndices,
rectVertices
);
// Load the mesh // Load the mesh
testMeshes = loadGltfMeshes(this, _modelPath).value(); testMeshes = loadGltfMeshes(this, _modelPath).value();
// Todo
// Destroy here (queue) // Delete the default data on engine shutdown
_mainDeletionQueue.pushFunction([this](){
#ifdef DEBUG
_logger.logConsole(CLEANUP, EINFO, "Default Data");
#endif
destroyBuffer(rectangle.indexBuffer);
destroyBuffer(rectangle.vertexBuffer);
});
#ifdef DEBUG #ifdef DEBUG
_logger.logRAM(ENGINE, EINIT, "Default data created !"); _logger.logRAM(ENGINE, EINIT, "Default data created !");
#endif #endif
@ -1660,7 +1739,7 @@ void Engine::createSwapchain(
uint32_t height uint32_t height
) { ) {
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Init] Creating the Swapchain..."); _logger.logRAM(ENGINE, EINIT, "Creating the Swapchain with dimensions {}x{}", width, height);
#endif #endif
vkb::SwapchainBuilder swapchainBuilder { vkb::SwapchainBuilder swapchainBuilder {
_choosenGPU, _choosenGPU,
@ -1692,10 +1771,11 @@ void Engine::createSwapchain(
_swapchainImageViews = { vkbSwapchain.get_image_views().value() }; _swapchainImageViews = { vkbSwapchain.get_image_views().value() };
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Info] Swapchain created with dimentions {} by {}", vkbSwapchain.extent.width, vkbSwapchain.extent.height); _logger.logRAM(ENGINE, EINFO, "Swapchain created with dimentions {}x{}", vkbSwapchain.extent.width, vkbSwapchain.extent.height);
#endif #endif
} }
// Ran once/frame, no logs because it will be noise
void Engine::buildImgui() { void Engine::buildImgui() {
// New frames // New frames
ImGui_ImplVulkan_NewFrame(); ImGui_ImplVulkan_NewFrame();
@ -1716,13 +1796,15 @@ void Engine::buildImgui() {
)) { )) {
ImVec2 size = ImGui::GetWindowSize(); ImVec2 size = ImGui::GetWindowSize();
if (size.x > 0 && size.y > 0) { if (size.x > 0 && size.y > 0) {
// Resize viewport render image if dock size changed // Panel size is used to determine
if ((uint32_t)size.x != _drawImage.imageExtent.width || // render target for this frame
(uint32_t)size.y != _drawImage.imageExtent.height) { _viewportPanelSize = { (uint32_t)size.x, (uint32_t)size.y };
resizeRenderImage((uint32_t)size.x, (uint32_t)size.y);
} ImVec2 uv1(
// Display the texture filling the zone (float)_drawExtent.width / (float)_drawImage.imageExtent.width,
ImGui::Image(_viewportTextureID, size); (float)_drawExtent.height / (float)_drawImage.imageExtent.height
);
ImGui::Image(_viewportTextureID, size, ImVec2(0, 0), uv1);
} }
} }
ImGui::End(); ImGui::End();
@ -1736,6 +1818,8 @@ void Engine::buildImgui() {
if(ImGui::Begin("Background Shader control")) { if(ImGui::Begin("Background Shader control")) {
ComputeEffect& selected = backgroundEffects[currentBackgroundEffect]; ComputeEffect& selected = backgroundEffects[currentBackgroundEffect];
ImGui::SliderFloat("Render scale", &renderScale, 0.3f, 1.0f);
ImGui::Text( ImGui::Text(
"Selected effect: %s", "Selected effect: %s",
selected.name selected.name
@ -1778,6 +1862,18 @@ void Engine::buildImgui() {
} }
ImGui::End(); ImGui::End();
// Stats
if(ImGui::Begin("Stats")) {
// Todo:
// Frametime
// Triangle count
// Etc...
ImGui::TextWrapped("GPU memory usage : %.2f KiB", _gpuMemusage/1024.0f);
ImGui::TextWrapped("Swapchain dimensions : %ix%i", _swapchainExtent.width, _swapchainExtent.height);
}
ImGui::End();
// Memory editor // Memory editor
if(ImGui::Begin("Memory")) { if(ImGui::Begin("Memory")) {
_memEdit.DrawContents(this, sizeof(*this), (size_t)this); _memEdit.DrawContents(this, sizeof(*this), (size_t)this);
@ -1790,17 +1886,13 @@ void Engine::buildImgui() {
void Engine::destroySwapchain() { void Engine::destroySwapchain() {
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Cleanup] Destroying the swapchain..."); _logger.logConsole(CLEANUP, EINFO, "Swapchain");
#endif #endif
vkDestroySwapchainKHR(_device, _swapchain, nullptr); vkDestroySwapchainKHR(_device, _swapchain, nullptr);
for (uint32_t i = 0; i < _swapchainImageViews.size(); i++) { for (uint32_t i = 0; i < _swapchainImageViews.size(); i++) {
vkDestroyImageView(_device, _swapchainImageViews[i], nullptr); vkDestroyImageView(_device, _swapchainImageViews[i], nullptr);
} }
#ifdef DEBUG
fmt::println("[Engine:Cleanup] Swapchain destroyed !");
#endif
} }
void Engine::drawBackground( void Engine::drawBackground(
@ -1938,21 +2030,30 @@ void Engine::drawGeometry(
&pushConstants &pushConstants
); );
vkCmdBindIndexBuffer(
cmd,
rectangle.indexBuffer.buffer,
0,
VK_INDEX_TYPE_UINT32
);
// Draw the rectangle
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
// Model // Model
// Correct the matrix // Correct the matrix
glm::mat4 view = glm::translate(glm::vec3{ 0, 0, -5}); glm::mat4 view = glm::translate(glm::vec3{ 0, 0, -5});
// Camera projection // Camera projection
/*
glm::mat4 projection = glm::perspective( glm::mat4 projection = glm::perspective(
glm::radians(70.0f), glm::radians(70.0f),
(float)_drawExtent.width / (float)_drawExtent.height, (float)_drawExtent.width / (float)_drawExtent.height,
10000.0f, 10000.0f,
0.1f 0.1f
); );
*/
// Invert the Y direction // Invert the Y direction
//projection[1][1] *= -1; projection[1][1] *= -1;
//pushConstants.worldMatrix = projection * view; pushConstants.worldMatrix = projection * view;
pushConstants.vertexBuffer = testMeshes[2]->meshBuffers.vertexBufferAddress; pushConstants.vertexBuffer = testMeshes[2]->meshBuffers.vertexBufferAddress;
vkCmdPushConstants( vkCmdPushConstants(
@ -2109,90 +2210,6 @@ void Engine::resizeSwapchain() {
#endif #endif
} }
void Engine::resizeRenderImage(uint32_t width, uint32_t height) {
#ifdef DEBUG
_logger.logRAM(ENGINE,EINFO, "Resizing render image to {}x{}", width, height);
#endif
vkDeviceWaitIdle(_device);
// Remove old ImGui texture
if (_viewportTextureID) {
ImGui_ImplVulkan_RemoveTexture(_viewportTextureID);
_viewportTextureID = nullptr;
}
// Destroy old draw image and view
vmaDestroyImage(_allocator, _drawImage.image, _drawImage.allocation);
vkDestroyImageView(_device, _drawImage.imageView, nullptr);
// Create new image with new extents
VkExtent3D newExtent = { width, height, 1 };
_drawImage.imageExtent = newExtent;
VkImageUsageFlags drawImageUsages {
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_STORAGE_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT
};
VkImageCreateInfo rImgInfo = vkinit::imageCreateInfo(
_drawImage.imageFormat,
drawImageUsages,
newExtent
);
VmaAllocationCreateInfo rImgAllocInfo = {
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
};
vmaCreateImage(
_allocator,
&rImgInfo,
&rImgAllocInfo,
&_drawImage.image,
&_drawImage.allocation,
nullptr
);
VkImageViewCreateInfo rViewInfo = vkinit::imageViewCreateInfo(
_drawImage.imageFormat,
_drawImage.image,
VK_IMAGE_ASPECT_COLOR_BIT
);
VK_CHECK(vkCreateImageView(_device, &rViewInfo, nullptr, &_drawImage.imageView));
// Update compute descriptor set with new image view
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);
// Re-register texture for ImGui
_viewportTextureID = ImGui_ImplVulkan_AddTexture(
_viewportSampler,
_drawImage.imageView,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
);
#ifdef DEBUG
fmt::println("[Engine:Utils] Render image resized !");
#endif
}
// CLI functions // CLI functions
void Engine::getAvailableGPU() { void Engine::getAvailableGPU() {
// Creates a temporary Vulkan Instance // Creates a temporary Vulkan Instance

View File

@ -14,8 +14,8 @@ class ArgHandler {
CLI::App* _run; CLI::App* _run;
// All options // All options
bool _listGPU {false}; bool _listGPU {false};
int _gpuIndex {-1}; EngineConfig config;
std::string _modelPath;
void buildArgs() { void buildArgs() {
// Setup // Setup
@ -33,8 +33,8 @@ class ArgHandler {
// Subcommand options/flags // Subcommand options/flags
// Run // Run
_run->add_option("--gpu, -g", _gpuIndex, "Manually select a GPU"); _run->add_option("--gpu, -g", config.gpuIndex, "Manually select a GPU");
_run->add_option("--model, -m", _modelPath, "Overwrites the default model"); _run->add_option("--model, -m", config.modelPath, "Overwrites the default model");
} }
int dispatch(int argc, char* argv[]) { int dispatch(int argc, char* argv[]) {
@ -85,8 +85,7 @@ int main(int argc, char* argv[]) {
if(handler._run->parsed()){ if(handler._run->parsed()){
engine.parseConfig( engine.parseConfig(
handler._gpuIndex, handler.config
handler._modelPath
); );
engine.init(); engine.init();