From 03a30c00964463dee1017ac90c406fd17db21bfa Mon Sep 17 00:00:00 2001 From: Alexandre Date: Mon, 4 May 2026 19:11:00 +0200 Subject: [PATCH] Fixed a CMake error --- .clangd | 1 + CMakeLists.txt | 25 ++++--- shaders/gradient.comp | 22 +++++++ src/buildInfo.hpp.in | 12 ---- src/engine/descriptors.h | 100 ++++++++++++++++++++++++++++ src/engine/engine.h | 139 +++++++++++++++++++++++++++++++-------- src/engine/images.h | 74 +++++++++++++++++++++ 7 files changed, 325 insertions(+), 48 deletions(-) create mode 100644 shaders/gradient.comp delete mode 100644 src/buildInfo.hpp.in create mode 100644 src/engine/descriptors.h diff --git a/.clangd b/.clangd index 93988a7..5b4213e 100644 --- a/.clangd +++ b/.clangd @@ -5,3 +5,4 @@ CompileFlags: - -DIMAGES_IMPL - -DINITIALIZERS_IMPL - -DPIPELINES_IMPL + - -DDESCRIPTORS_IMPL diff --git a/CMakeLists.txt b/CMakeLists.txt index cec3392..dd2bcff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,9 @@ find_package( glfw3 REQUIRED ) find_package( glm REQUIRED ) find_package( VulkanMemoryAllocator CONFIG REQUIRED ) find_package( fmt REQUIRED ) -find_package( Git QUIET ) +# Shader compilers +# Todo +#find_program( GLSLANG_VALIDATOR "glslangValidator" HINTS $ENV{VULKAN_SDK}/bin REQUIRED ) # fastgltf because it's not in nixpkgs @@ -47,8 +49,10 @@ FetchContent_MakeAvailable(vk-bootstrap) # A function to automate executables aditions function ( addBinary BINARY_NAME ) - cmake_parse_arguments ( BINARY "" "SHADER" "LIBS;TEXTURES;MODELS" ${ARGN} ) - add_executable ( ${BINARY_NAME} src/${BINARY_NAME}.cpp ) + cmake_parse_arguments ( BINARY "" "SOURCE" "SHADER;LIBS;TEXTURES;MODELS" ${ARGN} ) + if (DEFINED BINARY_SOURCE) + add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp ) + endif() # Sets the output dir to have clear separation between binaries set_target_properties ( ${BINARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BINARY_NAME} ) set_target_properties ( ${BINARY_NAME} PROPERTIES CXX_STANDARD 20 ) # Uses C++20 @@ -61,12 +65,12 @@ function ( addBinary BINARY_NAME ) # Define VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS to treat VK_ERROR_OUT_OF_DATE_KHR as a success code target_compile_definitions ( - ${BINARY_NAME} - PRIVATE - "VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS" - $<$:DEBUG> # So CMAKE expose a #define DEBUG for debug builds - # Exposes versions - BUILD_ID="${ENGINE_VERSION}" + ${BINARY_NAME} + PRIVATE + "VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS" + $<$:DEBUG> # So CMAKE expose a #define DEBUG for debug builds + # Exposes versions + BUILD_ID="${ENGINE_VERSION}" ) @@ -107,7 +111,8 @@ endfunction() # Adds the main binary addBinary ( - main + engine + SOURCE main LIBS glfw fmt vk-bootstrap vulkan ) diff --git a/shaders/gradient.comp b/shaders/gradient.comp new file mode 100644 index 0000000..7b267fd --- /dev/null +++ b/shaders/gradient.comp @@ -0,0 +1,22 @@ +// GLSL version +#version 460 + +layout ( local_size_x = 16, local_size_y = 16 ) in; + +layout ( rgba16f, set = 0, binding = 0 ) uniform image2D image; + +void main() { + ivec2 texelCoord = ivec2( gl_GlobalInvocationID.xy ); + ivec2 size = imageSize( image ); + + if ( texelCoord.x < size.x && texelCoord.y < size.y ) { + vec4 color = vec4( 0.0, 0.0, 0.0, 1.0 ); + + if ( gl_LocalInvocationID.x != 0 && gl_LocalInvocationID.y != 0 ) { + color.x = float(texelCoord.x)/(size.x); + color.y = float(texelCoord.y)/(size.y); + } + + imageStore(image, texelCoord, color); + } +} diff --git a/src/buildInfo.hpp.in b/src/buildInfo.hpp.in deleted file mode 100644 index e5624f0..0000000 --- a/src/buildInfo.hpp.in +++ /dev/null @@ -1,12 +0,0 @@ -// This file is auto generated by CMAKE -// Do not edit. -#pragma once - -// Short current commit git hash -#define BUILD_GIT_HASH "@GIT_HASH@" - -// UTC Timestamp -#define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@" - -// Build ID -#define BUILD_ID "@GIT_HASH@-@BUILD_TIMESTAMP@" diff --git a/src/engine/descriptors.h b/src/engine/descriptors.h new file mode 100644 index 0000000..c0218da --- /dev/null +++ b/src/engine/descriptors.h @@ -0,0 +1,100 @@ +#ifndef DESCRIPTORS_H +#define DESCRIPTORS_H +// Header +// Other includes +#include "types.h" +#include +#include + + +struct DescriptorLayoutBuilder { + std::vector bindings; + + void addBinding( + uint32_t binding, + VkDescriptorType type + ); + + void clear(); + + VkDescriptorSetLayout build ( + VkDevice device, + VkShaderStageFlags shaderStages, + void* pNext = nullptr, + VkDescriptorSetLayoutCreateFlags flags = 0 + ); +}; + +#endif + +#ifdef DESCRIPTORS_IMPL +#ifndef DESCRIPTORS_IMPL_H +#define DESCRIPTORS_IMPL_H +// The actual implementation + +void DescriptorLayoutBuilder::addBinding( + uint32_t binding, + VkDescriptorType type +){ + #ifdef DEBUG + fmt::println("Adding a descriptor set binding..."); + #endif + VkDescriptorSetLayoutBinding newBind { + .binding = binding, + .descriptorType = type, + .descriptorCount = 1 + }; + + bindings.push_back(newBind); +} + +void DescriptorLayoutBuilder::clear() { + #ifdef DEBUG + fmt::println("Clearing a descriptor set..."); + #endif + + bindings.clear(); + + +} + +VkDescriptorSetLayout DescriptorLayoutBuilder::build ( + VkDevice device, + VkShaderStageFlags shaderStages, + void* pNext = nullptr, + VkDescriptorSetLayoutCreateFlags flags = 0 +) { + #ifdef DEBUG + fmt::println("Building a descriptor set..."); + #endif + + for (auto& b : bindings) { + b.stageFlags |= shaderStages; + } + + VkDescriptorSetLayoutCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = pNext, + + .flags = flags, + .bindingCount = (uint32_t)bindings.size(), + .pBindings = bindings.data(), + }; + + VkDescriptorSet set; + + VK_CHECK( + vkCreateDescriptorSetLayout( + device, + &info, + nullptr, + &set + ) + ); + + return set; + +} + +#endif +#endif diff --git a/src/engine/engine.h b/src/engine/engine.h index 82b9d4f..8966c3d 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -3,15 +3,15 @@ // Normal header #include "types.h" -#include -#include +#include #include struct FrameData { VkCommandPool _commandPool; VkCommandBuffer _mainCommandBuffer; - VkSemaphore _swapchainSemaphore, _renderSemaphore; + VkSemaphore _swapchainSemaphore; + VkSemaphore _renderSemaphore; VkFence _renderFence; DeletionQueue _deletionQueue; }; @@ -72,8 +72,14 @@ class Engine { void initCommands(); void initSyncStructures(); - void createSwapchain(uint32_t width, uint32_t height); + void createSwapchain( + uint32_t width, + uint32_t height + ); void destroySwapchain(); + void drawBackground( + VkCommandBuffer cmd + ); }; #endif @@ -207,43 +213,83 @@ void Engine::cleanup() { void Engine::draw() { // wait until the gpu has finished rendering the last frame. Timeout of 1s - VK_CHECK(vkWaitForFences(_device, 1, &getCurrentFrame()._renderFence, true, 1000000000)); - // Flush frame data + VK_CHECK(vkWaitForFences(_device, 1, &getCurrentFrame()._renderFence, true, UINT64_MAX)); + + // Flush frame data getCurrentFrame()._deletionQueue.flush(); - // Reset fences to redo sync - VK_CHECK(vkResetFences(_device, 1, &getCurrentFrame()._renderFence)); // Request image from the swapchain uint32_t swapchainImageIndex; - VK_CHECK(vkAcquireNextImageKHR(_device, _swapchain, 1000000000, getCurrentFrame()._swapchainSemaphore, nullptr, &swapchainImageIndex)); + VK_CHECK(vkAcquireNextImageKHR(_device, _swapchain, UINT64_MAX, getCurrentFrame()._swapchainSemaphore, nullptr, &swapchainImageIndex)); + + // Reset fences to redo sync + VK_CHECK(vkResetFences(_device, 1, &getCurrentFrame()._renderFence)); VkCommandBuffer cmd = getCurrentFrame()._mainCommandBuffer; + _drawExtent.width = _drawImage.imageExtent.width; + _drawExtent.height = _drawImage.imageExtent.height; + VK_CHECK(vkResetCommandBuffer(cmd, 0)); - VkCommandBufferBeginInfo cmdBeginInfo = vkinit::commandBufferBeginInfo(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + VkCommandBufferBeginInfo cmdBeginInfo = { + vkinit::commandBufferBeginInfo( + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + ) + }; VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); - vkutil::transitionImage(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); + vkutil::transitionImage( + cmd, + _drawImage.image, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL + ); - VkClearColorValue clearValue; - float flash = std::abs(std::sin(_frameNumber / 120.f)); - clearValue = { { 0.0f, 0.0f, flash, 1.0f } }; + drawBackground(cmd); - VkImageSubresourceRange clearRange = vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT); - vkCmdClearColorImage(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange); + // Transfer the draw image and swapchain image to the correct layouts + vkutil::transitionImage( + cmd, + _drawImage.image, + VK_IMAGE_LAYOUT_GENERAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL + ); - vkutil::transitionImage(cmd, _swapchainImages[swapchainImageIndex],VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + vkutil::transitionImage( + cmd, + _swapchainImages[swapchainImageIndex], + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL + ); + // Copy image -> swapchain + vkutil::copyImageToImage( + cmd, + _drawImage.image, + _swapchainImages[swapchainImageIndex], + _drawExtent, + _swapchainExtent + ); + + // Uses the present layout to display into the screen + vkutil::transitionImage( + cmd, + _swapchainImages[swapchainImageIndex], + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR + ); + + // Locks the buffer, allowing it to be executed VK_CHECK(vkEndCommandBuffer(cmd)); VkCommandBufferSubmitInfo cmdinfo = vkinit::commandBufferSubmitInfo(cmd); - VkSemaphoreSubmitInfo waitInfo = vkinit::semaphoreSubmitInfo(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,getCurrentFrame()._swapchainSemaphore); + VkSemaphoreSubmitInfo waitInfo = vkinit::semaphoreSubmitInfo(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, getCurrentFrame()._swapchainSemaphore); VkSemaphoreSubmitInfo signalInfo = vkinit::semaphoreSubmitInfo(VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT, getCurrentFrame()._renderSemaphore); - VkSubmitInfo2 submit = vkinit::submitInfo(&cmdinfo,&signalInfo,&waitInfo); + VkSubmitInfo2 submit = vkinit::submitInfo(&cmdinfo, &signalInfo, &waitInfo); VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, getCurrentFrame()._renderFence)); @@ -422,6 +468,7 @@ void Engine::initSwapchain() { vmaCreateImage( _allocator, &rImgInfo, + &rImgAllocInfo, &_drawImage.image, &_drawImage.allocation, nullptr @@ -431,7 +478,7 @@ void Engine::initSwapchain() { vkinit::imageViewCreateInfo( _drawImage.imageFormat, _drawImage.image, - VK_IMAGE_ASPECT_DEPTH_BIT + VK_IMAGE_ASPECT_COLOR_BIT ) }; @@ -445,7 +492,7 @@ void Engine::initSwapchain() { ); // Add to deletion queues - _mainDeletionQueue.pushFunction([=]() { + _mainDeletionQueue.pushFunction([this]() { vkDestroyImageView( _device, _drawImage.imageView, @@ -456,7 +503,7 @@ void Engine::initSwapchain() { _drawImage.image, _drawImage.allocation ); - }) + }); #ifdef DEBUG fmt::println("Swapchain initialized !"); @@ -468,14 +515,32 @@ void Engine::initCommands() { fmt::println("Initializing vulkan commands.."); #endif - VkCommandPoolCreateInfo commandPoolInfo = { vkinit::commandPoolCreateInfo(_graphicsQueueFamily, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT) }; + VkCommandPoolCreateInfo commandPoolInfo = { + vkinit::commandPoolCreateInfo( + _graphicsQueueFamily, + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + ) + }; - for (uint32_t i = 0; i < FRAME_OVERLAP; i++) { - VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_frames[i]._commandPool)); + for ( uint32_t i = 0; i < FRAME_OVERLAP; i++ ) { + VK_CHECK( + vkCreateCommandPool( + _device, + &commandPoolInfo, + nullptr, + &_frames[i]._commandPool + ) + ); VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::commandBufferAllocateInfo(_frames[i]._commandPool, 1); - VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_frames[i]._mainCommandBuffer)); + VK_CHECK( + vkAllocateCommandBuffers( + _device, + &cmdAllocInfo, + &_frames[i]._mainCommandBuffer + ) + ); } #ifdef DEBUG fmt::println("Vulan commands initialized !"); @@ -556,6 +621,28 @@ void Engine::destroySwapchain() { #endif } +void Engine::drawBackground( + VkCommandBuffer cmd +) { + VkClearColorValue clearValue; + + float flash = { std::abs(std::sin(_frameNumber / 120.0f)) }; + + clearValue = { { 0.0f, 0.0f, flash, 1.0f } }; + + VkImageSubresourceRange clearRange = vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT); + + // Clear Image + vkCmdClearColorImage( + cmd, + _drawImage.image, + VK_IMAGE_LAYOUT_GENERAL, + &clearValue, + 1, + &clearRange + ); +} + #endif #endif diff --git a/src/engine/images.h b/src/engine/images.h index 048a890..3091078 100644 --- a/src/engine/images.h +++ b/src/engine/images.h @@ -2,6 +2,8 @@ #define IMAGES_H // Normal header #include "types.h" +#include +#include namespace vkutil { void transitionImage( @@ -10,6 +12,14 @@ namespace vkutil { VkImageLayout currentLayout, VkImageLayout newLayout ); + + void copyImageToImage( + VkCommandBuffer cmd, + VkImage source, + VkImage destination, + VkExtent2D srcSize, + VkExtent2D dstSize + ); } #endif @@ -21,6 +31,8 @@ namespace vkutil { #include "initializers.h" namespace vkutil { + // Todo : + // Switch structs to designated initializers void transitionImage( VkCommandBuffer cmd, VkImage image, @@ -51,6 +63,68 @@ namespace vkutil { vkCmdPipelineBarrier2(cmd, &depInfo); } + + + void copyImageToImage( + VkCommandBuffer cmd, + VkImage source, + VkImage destination, + VkExtent2D srcSize, + VkExtent2D dstSize + ) { + VkImageBlit2 blitRegion { + .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2, + .pNext = nullptr, + .srcSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + + .srcOffsets = { + VkOffset3D { 0, 0, 0 }, + VkOffset3D { + (int32_t)srcSize.width, + (int32_t)srcSize.height, + 1 + } + }, + + .dstSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 + }, + + .dstOffsets = { + VkOffset3D { 0, 0, 0 }, + VkOffset3D { + (int32_t)dstSize.width, + (int32_t)dstSize.height, + 1 + } + }, + }; + + VkBlitImageInfo2 blitInfo = { + .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2, + .pNext = nullptr, + + .srcImage = source, + .srcImageLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + + .dstImage = destination, + .dstImageLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + + .regionCount = 1, + .pRegions = &blitRegion, + .filter = VK_FILTER_LINEAR, + }; + + vkCmdBlitImage2(cmd, &blitInfo); + } } #endif