diff --git a/src/vkcv/CommandStreamManager.cpp b/src/vkcv/CommandStreamManager.cpp index 872e91c54b1b64616ad5867926e6f656f44ccded..ced6c86cd2fd700386bc0ec6305511b90d25933a 100644 --- a/src/vkcv/CommandStreamManager.cpp +++ b/src/vkcv/CommandStreamManager.cpp @@ -4,105 +4,76 @@ #include "vkcv/Logger.hpp" namespace vkcv { - CommandStreamManager::CommandStreamManager() noexcept : m_core(nullptr){} - - CommandStreamManager::~CommandStreamManager() noexcept { - for (const auto& stream : m_commandStreams) { - if (stream.cmdBuffer && stream.cmdBuffer) { - m_core->getContext().getDevice().freeCommandBuffers(stream.cmdPool, stream.cmdBuffer); - } - } + + uint64_t CommandStreamManager::getIdFrom(const CommandStreamHandle &handle) const { + return handle.getId(); } - - void CommandStreamManager::init(Core* core) { - if (!core) { - vkcv_log(LogLevel::ERROR, "Requires valid core pointer"); + + CommandStreamHandle CommandStreamManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { + return CommandStreamHandle(id, destroy); + } + + void CommandStreamManager::destroyById(uint64_t id) { + auto& stream = getById(id); + + if (stream.cmdBuffer) { + getCore().getContext().getDevice().freeCommandBuffers(stream.cmdPool, stream.cmdBuffer); + stream.cmdBuffer = nullptr; + stream.callbacks.clear(); } - m_core = core; } + + CommandStreamManager::CommandStreamManager() noexcept : + HandleManager<CommandStreamEntry, CommandStreamHandle>() {} - CommandStreamHandle CommandStreamManager::createCommandStream( - const vk::Queue &queue, - vk::CommandPool cmdPool) { - - const vk::CommandBuffer cmdBuffer = allocateCommandBuffer(m_core->getContext().getDevice(), cmdPool); - - CommandStream stream(cmdBuffer, queue, cmdPool); - beginCommandBuffer(stream.cmdBuffer, vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + CommandStreamManager::~CommandStreamManager() noexcept { + clear(); + } - // find unused stream - int unusedStreamIndex = -1; - for (size_t i = 0; i < m_commandStreams.size(); i++) { - if (m_commandStreams[i].cmdBuffer) { - // still in use - } else { - unusedStreamIndex = i; - break; + CommandStreamHandle CommandStreamManager::createCommandStream(const vk::Queue &queue, + vk::CommandPool cmdPool) { + const vk::CommandBuffer cmdBuffer = allocateCommandBuffer(getCore().getContext().getDevice(), cmdPool); + beginCommandBuffer(cmdBuffer, vk::CommandBufferUsageFlagBits::eOneTimeSubmit); + + for (uint64_t id = 0; id < getCount(); id++) { + auto& stream = getById(id); + + if (!(stream.cmdBuffer)) { + stream.cmdBuffer = cmdBuffer; + stream.cmdPool = cmdPool; + stream.queue = queue; + + return createById(id, [&](uint64_t id) { destroyById(id); }); } } - - const bool foundUnusedStream = unusedStreamIndex >= 0; - if (foundUnusedStream) { - m_commandStreams[unusedStreamIndex] = stream; - return CommandStreamHandle(unusedStreamIndex); - } - - CommandStreamHandle handle(m_commandStreams.size()); - m_commandStreams.push_back(stream); - return handle; + + return add({ cmdBuffer, cmdPool, queue, {} }); } - void CommandStreamManager::recordCommandsToStream( - const CommandStreamHandle &handle, - const RecordCommandFunction &record) { - - const size_t id = handle.getId(); - if (id >= m_commandStreams.size()) { - vkcv_log(LogLevel::ERROR, "Requires valid handle"); - return; - } - - CommandStream& stream = m_commandStreams[id]; + void CommandStreamManager::recordCommandsToStream(const CommandStreamHandle &handle, + const RecordCommandFunction &record) { + auto& stream = (*this)[handle]; record(stream.cmdBuffer); } - void CommandStreamManager::addFinishCallbackToStream( - const CommandStreamHandle &handle, - const FinishCommandFunction &finish) { - - const size_t id = handle.getId(); - if (id >= m_commandStreams.size()) { - vkcv_log(LogLevel::ERROR, "Requires valid handle"); - return; - } - - CommandStream& stream = m_commandStreams[id]; + void CommandStreamManager::addFinishCallbackToStream(const CommandStreamHandle &handle, + const FinishCommandFunction &finish) { + auto& stream = (*this)[handle]; stream.callbacks.push_back(finish); } - void CommandStreamManager::submitCommandStreamSynchronous( - const CommandStreamHandle &handle, - std::vector<vk::Semaphore> &waitSemaphores, - std::vector<vk::Semaphore> &signalSemaphores) { - - const size_t id = handle.getId(); - if (id >= m_commandStreams.size()) { - vkcv_log(LogLevel::ERROR, "Requires valid handle"); - return; - } - CommandStream& stream = m_commandStreams[id]; + void CommandStreamManager::submitCommandStreamSynchronous(const CommandStreamHandle &handle, + std::vector<vk::Semaphore> &waitSemaphores, + std::vector<vk::Semaphore> &signalSemaphores) { + auto& stream = (*this)[handle]; stream.cmdBuffer.end(); - const auto device = m_core->getContext().getDevice(); + const auto device = getCore().getContext().getDevice(); const vk::Fence waitFence = createFence(device); submitCommandBufferToQueue(stream.queue, stream.cmdBuffer, waitFence, waitSemaphores, signalSemaphores); waitForFence(device, waitFence); device.destroyFence(waitFence); - - device.freeCommandBuffers(stream.cmdPool, stream.cmdBuffer); - stream.cmdBuffer = nullptr; - stream.cmdPool = nullptr; - stream.queue = nullptr; + stream.queue = nullptr; for (const auto& finishCallback : stream.callbacks) { finishCallback(); @@ -110,11 +81,8 @@ namespace vkcv { } vk::CommandBuffer CommandStreamManager::getStreamCommandBuffer(const CommandStreamHandle &handle) { - const size_t id = handle.getId(); - if (id >= m_commandStreams.size()) { - vkcv_log(LogLevel::ERROR, "Requires valid handle"); - return nullptr; - } - return m_commandStreams[id].cmdBuffer; + auto& stream = (*this)[handle]; + return stream.cmdBuffer; } + } \ No newline at end of file diff --git a/src/vkcv/CommandStreamManager.hpp b/src/vkcv/CommandStreamManager.hpp index 9a8eb3d02143c20532275d5a61ca3cc68aa03778..044cb6bc0fc8758faa4973451b7cf9785c5e61ff 100644 --- a/src/vkcv/CommandStreamManager.hpp +++ b/src/vkcv/CommandStreamManager.hpp @@ -1,49 +1,44 @@ #pragma once + #include <vulkan/vulkan.hpp> #include <vector> + #include "vkcv/Event.hpp" -#include "vkcv/Handles.hpp" #include "vkcv/CommandRecordingFunctionTypes.hpp" +#include "HandleManager.hpp" + namespace vkcv { - class Core; + /** + * @brief Represents one command stream, into which commands can be recorded into. + * Consists of a command buffer, the command buffer's command pool and a queue, as well as some callbacks. + */ + struct CommandStreamEntry { + vk::CommandBuffer cmdBuffer; + vk::CommandPool cmdPool; + vk::Queue queue; + std::vector<FinishCommandFunction> callbacks; + }; /** * @brief Responsible for creation, deletion, callbacks and recording of command streams */ - class CommandStreamManager - { + class CommandStreamManager : public HandleManager<CommandStreamEntry, CommandStreamHandle> { friend class Core; private: - /** - * @brief Represents one command stream, into which commands can be recorded into. - * Consists of a command buffer, the command buffer's command pool and a queue, as well as some callbacks. - */ - struct CommandStream { - inline CommandStream(vk::CommandBuffer cmdBuffer, vk::Queue queue, vk::CommandPool cmdPool) - : cmdBuffer(cmdBuffer), cmdPool(cmdPool), queue(queue) {}; - vk::CommandBuffer cmdBuffer; - vk::CommandPool cmdPool; - vk::Queue queue; - std::vector<FinishCommandFunction> callbacks; - }; - - Core* m_core; - std::vector<CommandStream> m_commandStreams; - - CommandStreamManager() noexcept; - - void init(Core* core); + [[nodiscard]] + uint64_t getIdFrom(const CommandStreamHandle& handle) const override; + + [[nodiscard]] + CommandStreamHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; + + void destroyById(uint64_t id) override; public: - ~CommandStreamManager() noexcept; - - CommandStreamManager(CommandStreamManager&& other) = delete; - CommandStreamManager(const CommandStreamManager& other) = delete; - - CommandStreamManager& operator=(CommandStreamManager&& other) = delete; - CommandStreamManager& operator=(const CommandStreamManager& other) = delete; + CommandStreamManager() noexcept; + + ~CommandStreamManager() noexcept override; /** * @brief Creates a new command stream @@ -52,9 +47,8 @@ namespace vkcv { * @param cmdPool Command pool the command buffer will be allocated from * @return Handle that represents the #CommandStream */ - CommandStreamHandle createCommandStream( - const vk::Queue &queue, - vk::CommandPool cmdPool); + CommandStreamHandle createCommandStream(const vk::Queue &queue, + vk::CommandPool cmdPool); /** * @brief Record vulkan commands to a #CommandStream, using a record function @@ -62,7 +56,8 @@ namespace vkcv { * @param handle Command stream handle * @param record Function that records the vulkan commands */ - void recordCommandsToStream(const CommandStreamHandle &handle, const RecordCommandFunction &record); + void recordCommandsToStream(const CommandStreamHandle &handle, + const RecordCommandFunction &record); /** * @brief Add a callback to a #CommandStream that is called @@ -71,7 +66,8 @@ namespace vkcv { * @param handle Command stream handle * @param finish Callback that is called when a command stream submission is finished */ - void addFinishCallbackToStream(const CommandStreamHandle &handle, const FinishCommandFunction &finish); + void addFinishCallbackToStream(const CommandStreamHandle &handle, + const FinishCommandFunction &finish); /** * @brief Submits a #CommandStream to it's queue and returns after execution is finished @@ -80,10 +76,9 @@ namespace vkcv { * @param waitSemaphores Semaphores that are waited upon before executing the recorded commands * @param signalSemaphores Semaphores that are signaled when execution of the recorded commands is finished */ - void submitCommandStreamSynchronous( - const CommandStreamHandle &handle, - std::vector<vk::Semaphore> &waitSemaphores, - std::vector<vk::Semaphore> &signalSemaphores); + void submitCommandStreamSynchronous(const CommandStreamHandle &handle, + std::vector<vk::Semaphore> &waitSemaphores, + std::vector<vk::Semaphore> &signalSemaphores); /** * @brief Returns the underlying vulkan handle of a #CommandStream to be used for manual command recording @@ -92,6 +87,7 @@ namespace vkcv { * @return Vulkan handle of the #CommandStream */ vk::CommandBuffer getStreamCommandBuffer(const CommandStreamHandle &handle); + }; } \ No newline at end of file diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 821ae5e334e7f2be4e4c9d156d2a774a232e4718..d54e5c8594ac710f9919ac0d5cce1d66e1c4e2c3 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -57,9 +57,9 @@ namespace vkcv m_DescriptorSetLayoutManager(std::make_unique<DescriptorSetLayoutManager>()), m_DescriptorSetManager(std::make_unique<DescriptorSetManager>()), m_BufferManager(std::make_unique<BufferManager>()), - m_SamplerManager(std::unique_ptr<SamplerManager>(new SamplerManager(m_Context.m_Device))), + m_SamplerManager(std::make_unique<SamplerManager>()), m_ImageManager(std::make_unique<ImageManager>()), - m_CommandStreamManager{std::unique_ptr<CommandStreamManager>(new CommandStreamManager)}, + m_CommandStreamManager{std::make_unique<CommandStreamManager>()}, m_WindowManager(std::make_unique<WindowManager>()), m_SwapchainManager(std::make_unique<SwapchainManager>()), m_CommandResources(commandResources), @@ -72,7 +72,8 @@ namespace vkcv m_DescriptorSetLayoutManager->init(*this); m_DescriptorSetManager->init(*this, *m_DescriptorSetLayoutManager); m_BufferManager->init(*this); - m_CommandStreamManager->init(this); + m_SamplerManager->init(*this); + m_CommandStreamManager->init(*this); m_SwapchainManager->m_context = &m_Context; m_ImageManager->init(*this, *m_BufferManager); m_downsampler = std::unique_ptr<Downsampler>(new BlitDownsampler(*this, *m_ImageManager)); diff --git a/src/vkcv/SamplerManager.cpp b/src/vkcv/SamplerManager.cpp index 9a80635744e5a3dd0b6bd8db476cec841b1c317d..49accf6892560c1c8d3cd856cd1dd207bb214399 100644 --- a/src/vkcv/SamplerManager.cpp +++ b/src/vkcv/SamplerManager.cpp @@ -4,16 +4,29 @@ namespace vkcv { - SamplerManager::SamplerManager(const vk::Device& device) noexcept : - m_device(device), m_samplers() - {} + uint64_t SamplerManager::getIdFrom(const SamplerHandle &handle) const { + return handle.getId(); + } + + SamplerHandle SamplerManager::createById(uint64_t id, const HandleDestroyFunction &destroy) { + return SamplerHandle(id, destroy); + } - SamplerManager::~SamplerManager() { - for (uint64_t id = 0; id < m_samplers.size(); id++) { - destroySamplerById(id); + void SamplerManager::destroyById(uint64_t id) { + auto& sampler = getById(id); + + if (sampler) { + getCore().getContext().getDevice().destroySampler(sampler); + sampler = nullptr; } } + SamplerManager::SamplerManager() noexcept : HandleManager<vk::Sampler, SamplerHandle>() {} + + SamplerManager::~SamplerManager() noexcept { + clear(); + } + SamplerHandle SamplerManager::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter, SamplerMipmapMode mipmapMode, @@ -121,34 +134,15 @@ namespace vkcv { false ); - const vk::Sampler sampler = m_device.createSampler(samplerCreateInfo); + const vk::Sampler sampler = getCore().getContext().getDevice().createSampler( + samplerCreateInfo + ); - const uint64_t id = m_samplers.size(); - m_samplers.push_back(sampler); - return SamplerHandle(id, [&](uint64_t id) { destroySamplerById(id); }); + return add(sampler); } vk::Sampler SamplerManager::getVulkanSampler(const SamplerHandle &handle) const { - const uint64_t id = handle.getId(); - - if (id >= m_samplers.size()) { - return nullptr; - } - - return m_samplers[id]; - } - - void SamplerManager::destroySamplerById(uint64_t id) { - if (id >= m_samplers.size()) { - return; - } - - auto& sampler = m_samplers[id]; - - if (sampler) { - m_device.destroySampler(sampler); - sampler = nullptr; - } + return (*this)[handle]; } } diff --git a/src/vkcv/SamplerManager.hpp b/src/vkcv/SamplerManager.hpp index 24d89f0d6af151ff009a2f2bb64953d48a9e7213..3852d3be559b679710a64176ebe96c271ca92298 100644 --- a/src/vkcv/SamplerManager.hpp +++ b/src/vkcv/SamplerManager.hpp @@ -3,34 +3,30 @@ #include <vector> #include <vulkan/vulkan.hpp> -#include "vkcv/Handles.hpp" +#include "HandleManager.hpp" + #include "vkcv/Sampler.hpp" namespace vkcv { - class Core; - /** * @brief Class to manage the creation and destruction of samplers. */ - class SamplerManager { + class SamplerManager : public HandleManager<vk::Sampler, SamplerHandle> { friend class Core; private: - vk::Device m_device; - std::vector<vk::Sampler> m_samplers; + [[nodiscard]] + uint64_t getIdFrom(const SamplerHandle& handle) const override; - explicit SamplerManager(const vk::Device& device) noexcept; + [[nodiscard]] + SamplerHandle createById(uint64_t id, const HandleDestroyFunction& destroy) override; - void destroySamplerById(uint64_t id); + void destroyById(uint64_t id) override; public: - ~SamplerManager(); - - SamplerManager(const SamplerManager& other) = delete; - SamplerManager(SamplerManager&& other) = delete; + SamplerManager() noexcept; - SamplerManager& operator=(const SamplerManager& other) = delete; - SamplerManager& operator=(SamplerManager&& other) = delete; + ~SamplerManager() noexcept override; SamplerHandle createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter,