diff --git a/.envrc b/.envrc index 7652aae..3550a30 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1 @@ -FLAKEPATH="/home/alex/Developer/nix/NixOSDots/dev-flakes" - -use flake ${FLAKEPATH}/vulkan +use flake diff --git a/flake.nix b/flake.nix index 99d0f30..729c0dd 100644 --- a/flake.nix +++ b/flake.nix @@ -74,7 +74,9 @@ shellHook = '' echo "Vulkan loaded" + echo "MangoHud version: $(mangohud --version 2>/dev/null || echo 'non trouvée')" unset SOURCE_DATE_EPOCH + #unset NIX_ENFORCE_NO_NATIVE echo $LD_LIBRARY_PATH ''; }; diff --git a/src/Common/Types.h b/src/Common/Types.h index accc404..a00d716 100644 --- a/src/Common/Types.h +++ b/src/Common/Types.h @@ -23,9 +23,11 @@ #define GLFW_INCLUDE_VULKAN #include +#define GLM_ENABLE_EXPERIMENTAL +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#define GLM_FORCE_RADIANS #include #include -#define GLM_ENABLE_EXPERIMENTAL #include // Custom headers @@ -43,9 +45,16 @@ } \ } while (0) \ +// Enums +enum class RenderRez { + FIT, + R800x800, + R720p, + R1080p, + R2k +}; // Custom types - struct DeletionQueue { std::deque> deletors; @@ -80,6 +89,7 @@ struct AllocatedBuffer { VkBuffer buffer; VmaAllocation allocation; VmaAllocationInfo info; + uint32_t size; // In bytes }; struct Vertex { @@ -104,7 +114,8 @@ struct GPUDrawPushConstants { // Engine config struct EngineConfig { - int gpuIndex; + int gpuIndex {-1}; + std::string modelPath; }; // "Global" ? (I hope so) logger diff --git a/src/Engine/engine/engine.h b/src/Engine/engine/engine.h index 7836eb0..3ed4fd1 100644 --- a/src/Engine/engine/engine.h +++ b/src/Engine/engine/engine.h @@ -3,7 +3,8 @@ // Normal header // 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 "Common/Types.h" @@ -46,12 +47,15 @@ class Engine { public: //========== Class Members ========== // Config - int _gpuIndex {-1}; // Unitialized - bool _isInitialized { false }; - int _frameNumber { 0 }; - VkExtent2D _windowExtent; + EngineConfig _conf; + bool _isInitialized { false }; + int _frameNumber { 0 }; + VkExtent2D _viewportPanelSize { 1, 1 }; + VkExtent2D _windowExtent; - GLFWwindow *window { nullptr }; + GLFWwindow *window { nullptr }; + + uint32_t _gpuMemusage; // Vulkan specific class members VkInstance _instance; @@ -86,6 +90,7 @@ class Engine { AllocatedImage _drawImage; AllocatedImage _depthImage; // Depth testing VkExtent2D _drawExtent; + float renderScale = 1.0f; // Descriptor Sets DescriptorAllocator globalDescriptorAllocator; @@ -103,7 +108,6 @@ class Engine { // Resize bool _requestResize; - bool _requestRez; // Resolution // Push constants std::vector backgroundEffects; @@ -132,8 +136,7 @@ class Engine { std::vector> testMeshes; void parseConfig( - int gpuIndex, - std::string modelPath + EngineConfig conf ); void init(); @@ -203,10 +206,6 @@ class Engine { VkImageView targetImageView ); void resizeSwapchain(); - void resizeRenderImage( - uint32_t width, - uint32_t height - ); }; #endif @@ -277,16 +276,14 @@ constexpr bool bUseValidationLayers = false; //====================== void Engine::parseConfig( - int gpuIndex, - std::string modelPath + EngineConfig conf ) { - _gpuIndex = gpuIndex; + _conf = conf; - if(!modelPath.size() == 0) { + if(!conf.modelPath.size() == 0) { #ifdef DEBUG - _logger.logAll(ENGINE, EINFO, "Model overwrite, using {}", modelPath); + _logger.logAll(ENGINE, EINFO, "Model overwrite, using {}", conf.modelPath); #endif - _modelPath = modelPath; } } @@ -304,7 +301,7 @@ void Engine::init() { #endif if(!glfwInit()) { - throw std::runtime_error("Failed to init GLFW !"); + _logger.logFatal(ENGINE, "Failed to init GLFW !"); } // Get primary monitor @@ -345,6 +342,7 @@ void Engine::init() { void Engine::cleanup() { #ifdef DEBUG _logger.logConsole(CLEANUP, EINFO, "Cleaning up..."); + _logger.logConsole(CLEANUP, EINFO, "Total mem usage {} Bytes", _gpuMemusage); #endif if (_isInitialized) { // 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 VK_CHECK(vkWaitForFences(_device, 1, &getCurrentFrame()._renderFence, true, UINT64_MAX)); - // Flush frame data + // Flush frame data getCurrentFrame()._deletionQueue.flush(); // Request image from the swapchain @@ -407,7 +405,7 @@ void Engine::draw() { _requestResize = true; return; } 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 @@ -415,8 +413,8 @@ void Engine::draw() { VkCommandBuffer cmd = getCurrentFrame()._mainCommandBuffer; - _drawExtent.width = _drawImage.imageExtent.width; - _drawExtent.height = _drawImage.imageExtent.height; + _drawExtent.width = std::min(_viewportPanelSize.width, _drawImage.imageExtent.width) * renderScale; + _drawExtent.height = std::min(_viewportPanelSize.height, _drawImage.imageExtent.height) * renderScale; VK_CHECK(vkResetCommandBuffer(cmd, 0)); @@ -545,7 +543,7 @@ void Engine::draw() { _requestResize = true; return; } 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() { + // 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 _logger.logAll(ENGINE, EINFO,"Running..."); RunTimer timer; @@ -596,7 +598,6 @@ void Engine::run() { logger.clear(); } #ifdef DEBUG - // Not an error but logs to required targets _logger.logImportant(ENGINE, EINFO, "Engine has finished running after {} seconds!", timer.endTimer()); #endif } @@ -636,7 +637,7 @@ void Engine::initVulkan() { // Create the surface 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 @@ -653,7 +654,7 @@ void Engine::initVulkan() { .bufferDeviceAddress = true }; - if(_gpuIndex < 0) { + if(_conf.gpuIndex < 0) { // No overwrite, use VKB // Use vkBootstrap to select the GPU vkb::PhysicalDeviceSelector selector { vkbInst }; @@ -680,30 +681,29 @@ void Engine::initVulkan() { } else { // Overwrite, select GPU by hand #ifdef DEBUG - _logger.logAll(ENGINE, EINFO, "Manual GPU selection, choose {}", _gpuIndex); + _logger.logAll(ENGINE, EINFO, "Manual GPU selection, choose {}", _conf.gpuIndex); #endif uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(_instance, &deviceCount, nullptr); if (deviceCount == 0) { - throw std::runtime_error("[Engine:Error] No Vulkan GPU found !"); + _logger.logFatal(ENGINE, "No Vulkan GPU found !"); } std::vector devices(deviceCount); vkEnumeratePhysicalDevices(_instance, &deviceCount, devices.data()); - if (_gpuIndex >= deviceCount) { - throw std::runtime_error( - "[Engine:Error] GPU index " - + std::to_string(_gpuIndex) - + " out of bounds !(" - + std::to_string(deviceCount) - + " available GPUs)" + if (_conf.gpuIndex >= deviceCount) { + _logger.logFatal( + ENGINE, + "Invalid GPU index, there is {} available gpus (you selected {})", + deviceCount, + _conf.gpuIndex ); } - _choosenGPU = devices[_gpuIndex]; + _choosenGPU = devices[_conf.gpuIndex]; VkPhysicalDeviceProperties props{}; vkGetPhysicalDeviceProperties(_choosenGPU, &props); @@ -728,7 +728,7 @@ void Engine::initVulkan() { } 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(); @@ -759,7 +759,7 @@ void Engine::initVulkan() { }; 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); @@ -790,20 +790,27 @@ void Engine::initSwapchain() { #ifdef DEBUG _logger.logRAM(ENGINE, EINIT, "Initializing the swapchain..."); #endif - + /* glfwGetFramebufferSize( window, (int*)&_windowExtent.width, (int*)&_windowExtent.height ); + */ createSwapchain(_windowExtent.width, _windowExtent.height); - VkExtent3D drawImageExtent = { - _windowExtent.width, - _windowExtent.height, - 1 - }; + // Allocate the offscreen target once, at a big enough size + // so we don't need to reallocate. + const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + 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 _drawImage.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT; @@ -901,6 +908,9 @@ void Engine::initSwapchain() { // Add to deletion queue _mainDeletionQueue.pushFunction([this]() { + #ifdef DEBUG + _logger.logConsole(CLEANUP, EINFO, "Swapchain (draw images)"); + #endif // Draw image vkDestroyImageView( _device, @@ -928,6 +938,13 @@ void Engine::initSwapchain() { #ifdef DEBUG _logger.logRAM(ENGINE, EINIT, "Swapchain initialized !"); + _logger.logRAM( + ENGINE, + EINFO, + "DrawImage dimensions {} x {}", + drawImageExtent.width, + drawImageExtent.height + ); #endif } @@ -985,6 +1002,9 @@ void Engine::initCommands() { ); _mainDeletionQueue.pushFunction([this]() { + #ifdef DEBUG + _logger.logConsole(CLEANUP, EINFO, "Command pools (immediate"); + #endif vkDestroyCommandPool( _device, _immCommandPool, @@ -1040,6 +1060,9 @@ void Engine::initSyncStructures() { ); _syncDeletionQueue.pushFunction([this]() { + #ifdef DEBUG + _logger.logConsole(CLEANUP, EINFO, "Sync structures (immediate fences)"); + #endif vkDestroyFence( _device, _immFence, @@ -1048,13 +1071,13 @@ void Engine::initSyncStructures() { }); #ifdef DEBUG - fmt::println("[Engine:Init] Sync structures created !"); + _logger.logRAM(ENGINE, EINIT, "Sync structures created !"); #endif } void Engine::initDescriptors(){ #ifdef DEBUG - fmt::println("[Engine:Init] Initializing descriptors..."); + _logger.logRAM(ENGINE, EINIT, "Initializing descriptors..."); #endif std::vector sizes = { @@ -1105,6 +1128,9 @@ void Engine::initDescriptors(){ ); _mainDeletionQueue.pushFunction([this]() { + #ifdef DEBUG + _logger.logConsole(CLEANUP, EINFO, "Descriptors sets"); + #endif globalDescriptorAllocator.destroyPool(_device); vkDestroyDescriptorSetLayout( @@ -1115,13 +1141,13 @@ void Engine::initDescriptors(){ }); #ifdef DEBUG - fmt::println("[Engine:Init] Descriptors initialized !"); + _logger.logRAM(ENGINE, EINIT, "Descriptors initialized !"); #endif } void Engine::initImgui() { #ifdef DEBUG - fmt::println("[Engine:Init] Initializing ImGui..."); + _logger.logRAM(ENGINE, EINIT, "Initializing ImGui..."); #endif // Oversized descriptor pool for IMGUI, from the official tutorial // Ajust for optimization, or needs @@ -1196,6 +1222,8 @@ void Engine::initImgui() { ImGui_ImplVulkan_Init(&initInfo); // Create a sampler for Viewport rendering + // Todo + // Conversion to structs VkSamplerCreateInfo samplerInfo = {}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.magFilter = VK_FILTER_LINEAR; @@ -1217,6 +1245,9 @@ void Engine::initImgui() { ); _mainDeletionQueue.pushFunction([this, imguiPool]() { + #ifdef DEBUG + _logger.logConsole(CLEANUP, EINFO, "Imgui"); + #endif ImGui_ImplVulkan_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); @@ -1232,7 +1263,7 @@ void Engine::initImgui() { ); }); #ifdef DEBUG - fmt::println("[Engine:Init] ImGui initialized !"); + _logger.logRAM(ENGINE, EINIT, "ImGui initialized !"); #endif } @@ -1295,7 +1326,7 @@ void Engine::initBackgroundPipelines() { &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 @@ -1307,7 +1338,7 @@ void Engine::initBackgroundPipelines() { &skyShader ) ) { - fmt::println("[Engine:Error] Error while building the compute shader !"); + _logger.logFatal(ENGINE, "Error when building the sky compute shader !"); } // Fist Shader @@ -1386,6 +1417,9 @@ void Engine::initBackgroundPipelines() { ); _mainDeletionQueue.pushFunction([this, sky, gradient]() { + #ifdef DEBUG + _logger.logConsole(CLEANUP, EINFO, "Compute pipelines"); + #endif vkDestroyPipelineLayout( _device, _gradientPipelineLayout, @@ -1416,7 +1450,7 @@ void Engine::initMeshPipeline() { #endif VkShaderModule 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 { _logger.logRAM(ENGINE, EINFO, "Triangle fragment shader succesfully loaded"); @@ -1424,7 +1458,7 @@ void Engine::initMeshPipeline() { VkShaderModule 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 { _logger.logRAM(ENGINE, EINFO, "Triangle vertex shader succesfully loaded"); @@ -1499,6 +1533,10 @@ AllocatedBuffer Engine::createBuffer( VkBufferUsageFlags usage, 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 VkBufferCreateInfo bufferInfo { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -1513,6 +1551,7 @@ AllocatedBuffer Engine::createBuffer( }; AllocatedBuffer newBuffer; + newBuffer.size = allocSize; // Allocate the buffer VK_CHECK( @@ -1532,6 +1571,9 @@ AllocatedBuffer Engine::createBuffer( void Engine::destroyBuffer( const AllocatedBuffer& buffer ) { + #ifdef DEBUG + _gpuMemusage -= buffer.size; + #endif vmaDestroyBuffer( _allocator, buffer.buffer, @@ -1547,6 +1589,9 @@ GPUMeshBuffers Engine::uploadMesh( std::span indices, std::span vertices ) { + #ifdef DEBUG + _logger.logRAM(ENGINE, EINFO, "Uploading mesh..."); + #endif const size_t vertexBufferSize = vertices.size() * sizeof(Vertex); const size_t indexBufferSize = indices.size() * sizeof(uint32_t); @@ -1642,10 +1687,44 @@ void Engine::initDefaultData() { #ifdef DEBUG _logger.logRAM(ENGINE, EINIT, "Creating default data..."); #endif + std::array 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 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 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 _logger.logRAM(ENGINE, EINIT, "Default data created !"); #endif @@ -1660,7 +1739,7 @@ void Engine::createSwapchain( uint32_t height ) { #ifdef DEBUG - fmt::println("[Engine:Init] Creating the Swapchain..."); + _logger.logRAM(ENGINE, EINIT, "Creating the Swapchain with dimensions {}x{}", width, height); #endif vkb::SwapchainBuilder swapchainBuilder { _choosenGPU, @@ -1692,10 +1771,11 @@ void Engine::createSwapchain( _swapchainImageViews = { vkbSwapchain.get_image_views().value() }; #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 } +// Ran once/frame, no logs because it will be noise void Engine::buildImgui() { // New frames ImGui_ImplVulkan_NewFrame(); @@ -1716,13 +1796,15 @@ void Engine::buildImgui() { )) { ImVec2 size = ImGui::GetWindowSize(); if (size.x > 0 && size.y > 0) { - // Resize viewport render image if dock size changed - if ((uint32_t)size.x != _drawImage.imageExtent.width || - (uint32_t)size.y != _drawImage.imageExtent.height) { - resizeRenderImage((uint32_t)size.x, (uint32_t)size.y); - } - // Display the texture filling the zone - ImGui::Image(_viewportTextureID, size); + // Panel size is used to determine + // render target for this frame + _viewportPanelSize = { (uint32_t)size.x, (uint32_t)size.y }; + + ImVec2 uv1( + (float)_drawExtent.width / (float)_drawImage.imageExtent.width, + (float)_drawExtent.height / (float)_drawImage.imageExtent.height + ); + ImGui::Image(_viewportTextureID, size, ImVec2(0, 0), uv1); } } ImGui::End(); @@ -1736,6 +1818,8 @@ void Engine::buildImgui() { if(ImGui::Begin("Background Shader control")) { ComputeEffect& selected = backgroundEffects[currentBackgroundEffect]; + ImGui::SliderFloat("Render scale", &renderScale, 0.3f, 1.0f); + ImGui::Text( "Selected effect: %s", selected.name @@ -1778,6 +1862,18 @@ void Engine::buildImgui() { } 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 if(ImGui::Begin("Memory")) { _memEdit.DrawContents(this, sizeof(*this), (size_t)this); @@ -1790,17 +1886,13 @@ void Engine::buildImgui() { void Engine::destroySwapchain() { #ifdef DEBUG - fmt::println("[Engine:Cleanup] Destroying the swapchain..."); + _logger.logConsole(CLEANUP, EINFO, "Swapchain"); #endif vkDestroySwapchainKHR(_device, _swapchain, nullptr); for (uint32_t i = 0; i < _swapchainImageViews.size(); i++) { vkDestroyImageView(_device, _swapchainImageViews[i], nullptr); } - - #ifdef DEBUG - fmt::println("[Engine:Cleanup] Swapchain destroyed !"); - #endif } void Engine::drawBackground( @@ -1938,21 +2030,30 @@ void Engine::drawGeometry( &pushConstants ); + vkCmdBindIndexBuffer( + cmd, + rectangle.indexBuffer.buffer, + 0, + VK_INDEX_TYPE_UINT32 + ); + + // Draw the rectangle + vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0); + // Model // Correct the matrix glm::mat4 view = glm::translate(glm::vec3{ 0, 0, -5}); // Camera projection - /* + glm::mat4 projection = glm::perspective( glm::radians(70.0f), (float)_drawExtent.width / (float)_drawExtent.height, 10000.0f, 0.1f ); - */ // Invert the Y direction - //projection[1][1] *= -1; - //pushConstants.worldMatrix = projection * view; + projection[1][1] *= -1; + pushConstants.worldMatrix = projection * view; pushConstants.vertexBuffer = testMeshes[2]->meshBuffers.vertexBufferAddress; vkCmdPushConstants( @@ -2109,90 +2210,6 @@ void Engine::resizeSwapchain() { #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 void Engine::getAvailableGPU() { // Creates a temporary Vulkan Instance diff --git a/src/Engine/main.cpp b/src/Engine/main.cpp index 647c360..d87fb97 100644 --- a/src/Engine/main.cpp +++ b/src/Engine/main.cpp @@ -14,8 +14,8 @@ class ArgHandler { CLI::App* _run; // All options bool _listGPU {false}; - int _gpuIndex {-1}; - std::string _modelPath; + EngineConfig config; + void buildArgs() { // Setup @@ -33,8 +33,8 @@ class ArgHandler { // Subcommand options/flags // Run - _run->add_option("--gpu, -g", _gpuIndex, "Manually select a GPU"); - _run->add_option("--model, -m", _modelPath, "Overwrites the default model"); + _run->add_option("--gpu, -g", config.gpuIndex, "Manually select a GPU"); + _run->add_option("--model, -m", config.modelPath, "Overwrites the default model"); } int dispatch(int argc, char* argv[]) { @@ -85,8 +85,7 @@ int main(int argc, char* argv[]) { if(handler._run->parsed()){ engine.parseConfig( - handler._gpuIndex, - handler._modelPath + handler.config ); engine.init();