Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/graphics/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
target_sources(${PROJECT_NAME}
PRIVATE
vulkan/vk_command_buffers.cpp
vulkan/vk_command_buffers_container.cpp
vulkan/vk_descriptors.cpp
vulkan/vk_engine.cpp
vulkan/vk_images.cpp
Expand Down
22 changes: 11 additions & 11 deletions src/graphics/vulkan/vk_command_buffers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ void CommandBuffers::init_commands(VulkanEngine* vk_engine) {
vk_engine->_graphicsQueueFamily,
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);

for (auto& _frame : vk_engine->_frames) {
for (auto& _frame : vk_engine->command_buffers_container._frames) {
VkCommandPool commandPool;
VK_CHECK(vkCreateCommandPool(vk_engine->_device, &commandPoolInfo,
nullptr,
&commandPool));

_frame._commandPool = std::make_unique<VulkanCommandPool>(vk_engine->_device, commandPool);

// allocate the default command buffer that we will use for rendering
Expand All @@ -30,26 +30,26 @@ void CommandBuffers::init_commands(VulkanEngine* vk_engine) {
VkCommandPool immCommandPool;
VK_CHECK(vkCreateCommandPool(vk_engine->_device, &commandPoolInfo, nullptr,
&immCommandPool));
vk_engine->_immCommandPool = std::make_unique<VulkanCommandPool>(vk_engine->_device, immCommandPool);

vk_engine->command_buffers_container._immCommandPool = std::make_unique<VulkanCommandPool>(vk_engine->_device, immCommandPool);

// allocate the command buffer for immediate submits
const VkCommandBufferAllocateInfo cmdAllocInfo =
vkinit::command_buffer_allocate_info(vk_engine->_immCommandPool->get(), 1);
vkinit::command_buffer_allocate_info(vk_engine->command_buffers_container._immCommandPool->get(), 1);

VK_CHECK(vkAllocateCommandBuffers(vk_engine->_device, &cmdAllocInfo,
&(vk_engine->_immCommandBuffer)));
&(vk_engine->command_buffers_container._immCommandBuffer)));

// Smart pointer will automatically handle cleanup - no need for deletion queue
}

void CommandBuffers::immediate_submit(
std::function<void(VkCommandBuffer cmd)>&& function,
VulkanEngine* vk_engine) const {
VK_CHECK(vkResetFences(vk_engine->_device, 1, vk_engine->_immFence->getPtr()));
VK_CHECK(vkResetCommandBuffer(vk_engine->_immCommandBuffer, 0));
VK_CHECK(vkResetFences(vk_engine->_device, 1, vk_engine->command_buffers_container._immFence->getPtr()));
VK_CHECK(vkResetCommandBuffer(vk_engine->command_buffers_container._immCommandBuffer, 0));

const VkCommandBuffer cmd = vk_engine->_immCommandBuffer;
const VkCommandBuffer cmd = vk_engine->command_buffers_container._immCommandBuffer;

const VkCommandBufferBeginInfo cmdBeginInfo =
vkinit::command_buffer_begin_info(
Expand All @@ -69,8 +69,8 @@ void CommandBuffers::immediate_submit(
// submit command buffer to the queue and execute it.
// _renderFence will now block until the graphic commands finish execution
VK_CHECK(vkQueueSubmit2(vk_engine->_graphicsQueue, 1, &submit,
vk_engine->_immFence->get()));
vk_engine->command_buffers_container._immFence->get()));

VK_CHECK(vkWaitForFences(vk_engine->_device, 1, vk_engine->_immFence->getPtr(), true,
VK_CHECK(vkWaitForFences(vk_engine->_device, 1, vk_engine->command_buffers_container._immFence->getPtr(), true,
9999999999));
}
32 changes: 32 additions & 0 deletions src/graphics/vulkan/vk_command_buffers_container.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "graphics/vulkan/vk_command_buffers_container.h"
#include "graphics/vulkan/vk_engine.h"
#include "graphics/vulkan/vk_initializers.h"

CommandBuffersContainer::CommandBuffersContainer() {
// Initialize members - actual initialization happens in init_sync_structures
_immCommandBuffer = VK_NULL_HANDLE;
}

void CommandBuffersContainer::init_sync_structures(VulkanEngine* vk_engine) {
const VkFenceCreateInfo fenceCreateInfo =
vkinit::fence_create_info(VK_FENCE_CREATE_SIGNALED_BIT);
const VkSemaphoreCreateInfo semaphoreCreateInfo =
vkinit::semaphore_create_info();

for (auto& _frame : _frames) {
VkFence renderFence;
VK_CHECK(vkCreateFence(vk_engine->_device, &fenceCreateInfo, nullptr, &renderFence));
_frame._renderFence = std::make_unique<VulkanFence>(vk_engine->_device, renderFence);

VkSemaphore swapchainSemaphore, renderSemaphore;
VK_CHECK(vkCreateSemaphore(vk_engine->_device, &semaphoreCreateInfo, nullptr, &swapchainSemaphore));
VK_CHECK(vkCreateSemaphore(vk_engine->_device, &semaphoreCreateInfo, nullptr, &renderSemaphore));

_frame._swapchainSemaphore = std::make_unique<VulkanSemaphore>(vk_engine->_device, swapchainSemaphore);
_frame._renderSemaphore = std::make_unique<VulkanSemaphore>(vk_engine->_device, renderSemaphore);
}

VkFence immFence;
VK_CHECK(vkCreateFence(vk_engine->_device, &fenceCreateInfo, nullptr, &immFence));
_immFence = std::make_unique<VulkanFence>(vk_engine->_device, immFence);
}
29 changes: 3 additions & 26 deletions src/graphics/vulkan/vk_engine.cpp
Comment thread
Fra1sse marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void VulkanEngine::init_descriptors() {

writer.update_set(_device, _drawImageDescriptors);

for (auto& _frame : _frames) {
for (auto& _frame : command_buffers_container._frames) {
// create a descriptor pool
std::vector<DescriptorAllocatorGrowable::PoolSizeRatio> frame_sizes = {
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 3},
Expand Down Expand Up @@ -329,7 +329,7 @@ void VulkanEngine::init(SDL_Window* window) {

command_buffers.init_commands(this);

init_sync_structures();
command_buffers_container.init_sync_structures(this);
init_descriptors();
init_pipelines();
init_imgui();
Expand Down Expand Up @@ -466,29 +466,6 @@ void VulkanEngine::init_vulkan() {
// VMA allocator will be destroyed in cleanup() - no need for deletion queue
}

void VulkanEngine::init_sync_structures() {
const VkFenceCreateInfo fenceCreateInfo =
vkinit::fence_create_info(VK_FENCE_CREATE_SIGNALED_BIT);
const VkSemaphoreCreateInfo semaphoreCreateInfo =
vkinit::semaphore_create_info();

for (auto& _frame : _frames) {
VkFence renderFence;
VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &renderFence));
_frame._renderFence = std::make_unique<VulkanFence>(_device, renderFence);

VkSemaphore swapchainSemaphore, renderSemaphore;
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &swapchainSemaphore));
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &renderSemaphore));

_frame._swapchainSemaphore = std::make_unique<VulkanSemaphore>(_device, swapchainSemaphore);
_frame._renderSemaphore = std::make_unique<VulkanSemaphore>(_device, renderSemaphore);
}

VkFence immFence;
VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &immFence));
_immFence = std::make_unique<VulkanFence>(_device, immFence);
}

void VulkanEngine::create_swapchain(uint32_t width, uint32_t height) {
vkb::SwapchainBuilder swapchainBuilder{_chosenGPU, _device, _surface};
Expand Down Expand Up @@ -621,7 +598,7 @@ void VulkanEngine::cleanup() {

// Smart pointers will automatically clean up resources

for (auto& _frame : _frames) {
for (auto& _frame : command_buffers_container._frames) {
// Smart pointers automatically clean up sync objects
// Manual cleanup only for command pools and command buffers
if (_frame._commandPool) {
Expand Down
4 changes: 1 addition & 3 deletions src/graphics/vulkan/vk_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,7 @@ VkSamplerMipmapMode extract_mipmap_mode(fastgltf::Filter filter) {

std::optional<std::shared_ptr<LoadedGLTF>> loadGltf(VulkanEngine* engine,
std::string_view filePath) {
LOGI("Loading GLTF: {}", filePath);

if (!std::filesystem::exists(filePath)) {
LOGI("Loading GLTF: {}", filePath);if (!std::filesystem::exists(filePath)) {
LOGW("File does not exist: {}", filePath);
}
auto scene = std::make_shared<LoadedGLTF>();
Expand Down
50 changes: 50 additions & 0 deletions src/include/graphics/vulkan/vk_command_buffers_container.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <cstdint>
#include <memory>
#include <vector>
#include <vulkan/vulkan_core.h>

#include "vk_descriptors.h"
#include "vk_smart_wrappers.h"

constexpr unsigned int FRAME_OVERLAP = 2;

struct FrameData {
std::unique_ptr<VulkanCommandPool> _commandPool;
VkCommandBuffer _mainCommandBuffer;

std::unique_ptr<VulkanSemaphore> _swapchainSemaphore, _renderSemaphore;
std::unique_ptr<VulkanFence> _renderFence;

DescriptorAllocatorGrowable _frameDescriptors;
std::vector<std::unique_ptr<VulkanBuffer>> _frameBuffers; // For per-frame temporary buffers
};

class VulkanEngine;

class CommandBuffersContainer {
public:
CommandBuffersContainer();
~CommandBuffersContainer() = default;

// Frame management
FrameData _frames[FRAME_OVERLAP];

FrameData& get_current_frame(unsigned int frameNumber) {
return _frames[frameNumber % FRAME_OVERLAP];
}

// Immediate command buffer members
std::unique_ptr<VulkanFence> _immFence;
VkCommandBuffer _immCommandBuffer;
std::unique_ptr<VulkanCommandPool> _immCommandPool;

// Initialization
void init_sync_structures(VulkanEngine* vk_engine);

private:
// No copying
CommandBuffersContainer(const CommandBuffersContainer&) = delete;
CommandBuffersContainer& operator=(const CommandBuffersContainer&) = delete;
};
23 changes: 3 additions & 20 deletions src/include/graphics/vulkan/vk_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,14 @@
#include "ComputePipeline.h"

#include "vk_command_buffers.h"
#include "vk_command_buffers_container.h"

class Camera;
class VulkanEngine;
struct DrawContext;
struct LoadedGLTF;
struct MeshAsset;

constexpr unsigned int FRAME_OVERLAP = 2;

struct FrameData {
std::unique_ptr<VulkanCommandPool> _commandPool;
VkCommandBuffer _mainCommandBuffer;

std::unique_ptr<VulkanSemaphore> _swapchainSemaphore, _renderSemaphore;
std::unique_ptr<VulkanFence> _renderFence;

DescriptorAllocatorGrowable _frameDescriptors;
std::vector<std::unique_ptr<VulkanBuffer>> _frameBuffers; // For per-frame temporary buffers
};

struct GPUSceneData {
glm::mat4 view;
Expand Down Expand Up @@ -79,6 +68,7 @@ class VulkanEngine {
Pipelines pipelines;

CommandBuffers command_buffers;
CommandBuffersContainer command_buffers_container;

int64_t registerMesh(const std::string& filePath);

Expand All @@ -99,10 +89,8 @@ class VulkanEngine {

void update_scene();

FrameData _frames[FRAME_OVERLAP];

FrameData& get_current_frame() {
return _frames[_frameNumber % FRAME_OVERLAP];
return command_buffers_container.get_current_frame(_frameNumber);
};

VkQueue _graphicsQueue;
Expand Down Expand Up @@ -154,10 +142,6 @@ class VulkanEngine {
VkDescriptorSet _drawImageDescriptors;
VkDescriptorSetLayout _drawImageDescriptorLayout;

// immediate submit structures
std::unique_ptr<VulkanFence> _immFence;
VkCommandBuffer _immCommandBuffer;
std::unique_ptr<VulkanCommandPool> _immCommandPool;

GPUMeshBuffers rectangle;

Expand Down Expand Up @@ -209,7 +193,6 @@ class VulkanEngine {

void init_vulkan();
void init_swapchain();
void init_sync_structures();

void create_swapchain(uint32_t width, uint32_t height);
void destroy_swapchain();
Expand Down
Loading