Fixed a CMake error

This commit is contained in:
Alexandre 2026-05-04 19:11:00 +02:00
parent a3b498d11b
commit 03a30c0096
7 changed files with 325 additions and 48 deletions

View File

@ -5,3 +5,4 @@ CompileFlags:
- -DIMAGES_IMPL - -DIMAGES_IMPL
- -DINITIALIZERS_IMPL - -DINITIALIZERS_IMPL
- -DPIPELINES_IMPL - -DPIPELINES_IMPL
- -DDESCRIPTORS_IMPL

View File

@ -25,7 +25,9 @@ find_package( glfw3 REQUIRED )
find_package( glm REQUIRED ) find_package( glm REQUIRED )
find_package( VulkanMemoryAllocator CONFIG REQUIRED ) find_package( VulkanMemoryAllocator CONFIG REQUIRED )
find_package( fmt 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 # fastgltf because it's not in nixpkgs
@ -47,8 +49,10 @@ FetchContent_MakeAvailable(vk-bootstrap)
# A function to automate executables aditions # A function to automate executables aditions
function ( addBinary BINARY_NAME ) function ( addBinary BINARY_NAME )
cmake_parse_arguments ( BINARY "" "SHADER" "LIBS;TEXTURES;MODELS" ${ARGN} ) cmake_parse_arguments ( BINARY "" "SOURCE" "SHADER;LIBS;TEXTURES;MODELS" ${ARGN} )
add_executable ( ${BINARY_NAME} src/${BINARY_NAME}.cpp ) if (DEFINED BINARY_SOURCE)
add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp )
endif()
# Sets the output dir to have clear separation between binaries # 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 RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BINARY_NAME} )
set_target_properties ( ${BINARY_NAME} PROPERTIES CXX_STANDARD 20 ) # Uses C++20 set_target_properties ( ${BINARY_NAME} PROPERTIES CXX_STANDARD 20 ) # Uses C++20
@ -107,7 +111,8 @@ endfunction()
# Adds the main binary # Adds the main binary
addBinary ( addBinary (
main engine
SOURCE main
LIBS glfw fmt vk-bootstrap vulkan LIBS glfw fmt vk-bootstrap vulkan
) )

22
shaders/gradient.comp Normal file
View File

@ -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);
}
}

View File

@ -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@"

100
src/engine/descriptors.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef DESCRIPTORS_H
#define DESCRIPTORS_H
// Header
// Other includes
#include "types.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
struct DescriptorLayoutBuilder {
std::vector<VkDescriptorSetLayoutBinding> 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

View File

@ -3,15 +3,15 @@
// Normal header // Normal header
#include "types.h" #include "types.h"
#include <cstddef> #include <cstdint>
#include <fmt/base.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
struct FrameData { struct FrameData {
VkCommandPool _commandPool; VkCommandPool _commandPool;
VkCommandBuffer _mainCommandBuffer; VkCommandBuffer _mainCommandBuffer;
VkSemaphore _swapchainSemaphore, _renderSemaphore; VkSemaphore _swapchainSemaphore;
VkSemaphore _renderSemaphore;
VkFence _renderFence; VkFence _renderFence;
DeletionQueue _deletionQueue; DeletionQueue _deletionQueue;
}; };
@ -72,8 +72,14 @@ class Engine {
void initCommands(); void initCommands();
void initSyncStructures(); void initSyncStructures();
void createSwapchain(uint32_t width, uint32_t height); void createSwapchain(
uint32_t width,
uint32_t height
);
void destroySwapchain(); void destroySwapchain();
void drawBackground(
VkCommandBuffer cmd
);
}; };
#endif #endif
@ -207,35 +213,75 @@ void Engine::cleanup() {
void Engine::draw() { 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, 1000000000)); VK_CHECK(vkWaitForFences(_device, 1, &getCurrentFrame()._renderFence, true, UINT64_MAX));
// Flush frame data // Flush frame data
getCurrentFrame()._deletionQueue.flush(); getCurrentFrame()._deletionQueue.flush();
// Reset fences to redo sync
VK_CHECK(vkResetFences(_device, 1, &getCurrentFrame()._renderFence));
// Request image from the swapchain // Request image from the swapchain
uint32_t swapchainImageIndex; 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; VkCommandBuffer cmd = getCurrentFrame()._mainCommandBuffer;
_drawExtent.width = _drawImage.imageExtent.width;
_drawExtent.height = _drawImage.imageExtent.height;
VK_CHECK(vkResetCommandBuffer(cmd, 0)); 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)); 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; drawBackground(cmd);
float flash = std::abs(std::sin(_frameNumber / 120.f));
clearValue = { { 0.0f, 0.0f, flash, 1.0f } };
VkImageSubresourceRange clearRange = vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT); // Transfer the draw image and swapchain image to the correct layouts
vkCmdClearColorImage(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange); 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)); VK_CHECK(vkEndCommandBuffer(cmd));
VkCommandBufferSubmitInfo cmdinfo = vkinit::commandBufferSubmitInfo(cmd); VkCommandBufferSubmitInfo cmdinfo = vkinit::commandBufferSubmitInfo(cmd);
@ -422,6 +468,7 @@ void Engine::initSwapchain() {
vmaCreateImage( vmaCreateImage(
_allocator, _allocator,
&rImgInfo, &rImgInfo,
&rImgAllocInfo,
&_drawImage.image, &_drawImage.image,
&_drawImage.allocation, &_drawImage.allocation,
nullptr nullptr
@ -431,7 +478,7 @@ void Engine::initSwapchain() {
vkinit::imageViewCreateInfo( vkinit::imageViewCreateInfo(
_drawImage.imageFormat, _drawImage.imageFormat,
_drawImage.image, _drawImage.image,
VK_IMAGE_ASPECT_DEPTH_BIT VK_IMAGE_ASPECT_COLOR_BIT
) )
}; };
@ -445,7 +492,7 @@ void Engine::initSwapchain() {
); );
// Add to deletion queues // Add to deletion queues
_mainDeletionQueue.pushFunction([=]() { _mainDeletionQueue.pushFunction([this]() {
vkDestroyImageView( vkDestroyImageView(
_device, _device,
_drawImage.imageView, _drawImage.imageView,
@ -456,7 +503,7 @@ void Engine::initSwapchain() {
_drawImage.image, _drawImage.image,
_drawImage.allocation _drawImage.allocation
); );
}) });
#ifdef DEBUG #ifdef DEBUG
fmt::println("Swapchain initialized !"); fmt::println("Swapchain initialized !");
@ -468,14 +515,32 @@ void Engine::initCommands() {
fmt::println("Initializing vulkan commands.."); fmt::println("Initializing vulkan commands..");
#endif #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++ ) { for ( uint32_t i = 0; i < FRAME_OVERLAP; i++ ) {
VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_frames[i]._commandPool)); VK_CHECK(
vkCreateCommandPool(
_device,
&commandPoolInfo,
nullptr,
&_frames[i]._commandPool
)
);
VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::commandBufferAllocateInfo(_frames[i]._commandPool, 1); 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 #ifdef DEBUG
fmt::println("Vulan commands initialized !"); fmt::println("Vulan commands initialized !");
@ -556,6 +621,28 @@ void Engine::destroySwapchain() {
#endif #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
#endif #endif

View File

@ -2,6 +2,8 @@
#define IMAGES_H #define IMAGES_H
// Normal header // Normal header
#include "types.h" #include "types.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
namespace vkutil { namespace vkutil {
void transitionImage( void transitionImage(
@ -10,6 +12,14 @@ namespace vkutil {
VkImageLayout currentLayout, VkImageLayout currentLayout,
VkImageLayout newLayout VkImageLayout newLayout
); );
void copyImageToImage(
VkCommandBuffer cmd,
VkImage source,
VkImage destination,
VkExtent2D srcSize,
VkExtent2D dstSize
);
} }
#endif #endif
@ -21,6 +31,8 @@ namespace vkutil {
#include "initializers.h" #include "initializers.h"
namespace vkutil { namespace vkutil {
// Todo :
// Switch structs to designated initializers
void transitionImage( void transitionImage(
VkCommandBuffer cmd, VkCommandBuffer cmd,
VkImage image, VkImage image,
@ -51,6 +63,68 @@ namespace vkutil {
vkCmdPipelineBarrier2(cmd, &depInfo); 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 #endif