From ccbd7561f46b7f8b63689d3f30de0420c693b504 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sun, 7 Jan 2024 01:34:02 +0100 Subject: [PATCH] fixing better vk command buffers management --- .gdb_history | 1 + example/Test | Bin 14536 -> 0 bytes example/main.c | 4 +- src/core/UUID.cpp | 25 ++++ src/core/UUID.h | 48 +++++++ src/core/application.cpp | 20 ++- src/core/graphics.h | 4 +- src/renderer/buffers/vk_buffer.cpp | 33 ++--- .../command/single_time_cmd_manager.cpp | 22 ++- .../command/single_time_cmd_manager.h | 17 ++- src/renderer/command/vk_cmd_buffer.cpp | 126 +++++++++++++++--- src/renderer/command/vk_cmd_buffer.h | 28 ++-- src/renderer/core/cmd_resource.h | 28 +--- src/renderer/core/memory.cpp | 8 +- src/renderer/core/render_core.cpp | 40 +++++- src/renderer/core/render_core.h | 4 +- src/renderer/core/vk_fence.cpp | 5 +- src/renderer/core/vk_validation_layers.cpp | 47 +++++-- src/renderer/core/vk_validation_layers.h | 10 +- src/renderer/images/vk_image.cpp | 72 ++++------ src/renderer/images/vk_image.h | 10 +- src/renderer/renderer.cpp | 4 +- 22 files changed, 395 insertions(+), 161 deletions(-) create mode 100644 .gdb_history delete mode 100755 example/Test create mode 100644 src/core/UUID.cpp create mode 100644 src/core/UUID.h diff --git a/.gdb_history b/.gdb_history new file mode 100644 index 0000000..bca70f3 --- /dev/null +++ b/.gdb_history @@ -0,0 +1 @@ +q diff --git a/example/Test b/example/Test deleted file mode 100755 index 2a36f9cf146cc860f8188059bdbd23237bb5e972..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14536 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 diff --git a/example/main.c b/example/main.c index 7d09156..ffdacf9 100644 --- a/example/main.c +++ b/example/main.c @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */ -/* Updated: 2024/01/04 12:44:58 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:24:29 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -114,8 +114,8 @@ int main(int argc, char* argv[]) "that text will disappear"); mlx_loop_hook(mlx.mlx, update, &mlx); mlx_loop(mlx.mlx); - mlx_destroy_image(mlx.mlx, mlx.img); mlx_destroy_image(mlx.mlx, mlx.logo); + mlx_destroy_image(mlx.mlx, mlx.img); mlx_destroy_window(mlx.mlx, mlx.win); mlx_destroy_display(mlx.mlx); return (0); diff --git a/src/core/UUID.cpp b/src/core/UUID.cpp new file mode 100644 index 0000000..060f6ba --- /dev/null +++ b/src/core/UUID.cpp @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* UUID.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/06 11:26:37 by maldavid #+# #+# */ +/* Updated: 2024/01/06 11:28:15 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include + +namespace mlx +{ + static std::random_device random_device; + static std::mt19937_64 engine(random_device()); + static std::uniform_int_distribution uniform_distribution; + + UUID::UUID() : _uuid(uniform_distribution(engine)) {} + UUID::UUID(uint64_t uuid) : _uuid(uuid) {} +} diff --git a/src/core/UUID.h b/src/core/UUID.h new file mode 100644 index 0000000..1fd216a --- /dev/null +++ b/src/core/UUID.h @@ -0,0 +1,48 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* UUID.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/06 11:13:23 by maldavid #+# #+# */ +/* Updated: 2024/01/06 11:29:34 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_UUID__ +#define __MLX_UUID__ + +#include + +namespace mlx +{ + class UUID + { + public: + UUID(); + UUID(uint64_t uuid); + + inline operator uint64_t() const { return _uuid; } + + private: + uint64_t _uuid; + }; +} + +namespace std +{ + template struct hash; + + template<> + struct hash + { + std::size_t operator()(const mlx::UUID& uuid) const + { + return static_cast(uuid); + } + }; + +} + +#endif diff --git a/src/core/application.cpp b/src/core/application.cpp index 21bc253..1697a28 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 22:10:52 by maldavid #+# #+# */ -/* Updated: 2023/12/27 21:30:10 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:31:44 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -38,12 +38,19 @@ namespace mlx::core { _in->update(); + Render_Core::get().getSingleTimeCmdManager().updateSingleTimesCmdBuffersSubmitState(); + if(_loop_hook) _loop_hook(_param); for(auto& gs : _graphics) gs->render(); } + for(auto& gs : _graphics) + { + for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + gs->getRenderer().getCmdBuffer(i).waitForExecution(); + } } void* Application::newTexture(int w, int h) @@ -64,9 +71,16 @@ namespace mlx::core void Application::destroyTexture(void* ptr) { - vkDeviceWaitIdle(Render_Core::get().getDevice().get()); // TODO : synchronize with another method than stopping all the GPU process + if(ptr == nullptr) + { + core::error::report(e_kind::error, "wrong texture (NULL)"); + return; + } Texture* texture = static_cast(ptr); - texture->destroy(); + if(!texture->isInit()) + core::error::report(e_kind::error, "trying to destroy a texture that has already been destroyed"); + else + texture->destroy(); } Application::~Application() diff --git a/src/core/graphics.h b/src/core/graphics.h index 04f66b0..35cb991 100644 --- a/src/core/graphics.h +++ b/src/core/graphics.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/02 14:49:49 by maldavid #+# #+# */ -/* Updated: 2023/12/24 08:56:14 by kbz_8 ### ########.fr */ +/* Updated: 2024/01/07 01:27:09 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -47,6 +47,8 @@ namespace mlx inline void texturePut(Texture* texture, int x, int y); inline void loadFont(const std::filesystem::path& filepath, float scale); + inline Renderer& getRenderer() { return *_renderer; } + ~GraphicsSupport(); private: diff --git a/src/renderer/buffers/vk_buffer.cpp b/src/renderer/buffers/vk_buffer.cpp index a092d6d..ef8ec78 100644 --- a/src/renderer/buffers/vk_buffer.cpp +++ b/src/renderer/buffers/vk_buffer.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 18:55:57 by maldavid #+# #+# */ -/* Updated: 2023/12/17 17:35:03 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:18:35 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,15 +22,6 @@ namespace mlx { void Buffer::create(Buffer::kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data) { - CmdResource::setDestroyer([this]() - { - if(_is_mapped) - unmapMem(); - if(_buffer != VK_NULL_HANDLE) - Render_Core::get().getAllocator().destroyBuffer(_allocation, _buffer); - _buffer = VK_NULL_HANDLE; - }); - _usage = usage; if(type == Buffer::kind::constant || type == Buffer::kind::dynamic_device_local) { @@ -61,6 +52,15 @@ namespace mlx void Buffer::destroy() noexcept { + // not creating destroyer in `create` as some image may be copied (and so `this` will be invalid) + CmdResource::setDestroyer([this]() + { + if(_is_mapped) + unmapMem(); + if(_buffer != VK_NULL_HANDLE) + Render_Core::get().getAllocator().destroyBuffer(_allocation, _buffer); + _buffer = VK_NULL_HANDLE; + }); CmdResource::requireDestroy(); } @@ -101,13 +101,10 @@ namespace mlx return false; } - // TODO, use global cmd buffer pool to manage resources CmdBuffer& cmd = Render_Core::get().getSingleTimeCmdBuffer(); cmd.beginRecord(); - VkBufferCopy copyRegion{}; - copyRegion.size = _size; - vkCmdCopyBuffer(cmd.get(), buffer._buffer, _buffer, 1, ©Region); + cmd.copyBuffer(*this, const_cast(buffer)); cmd.endRecord(); cmd.submitIdle(); @@ -129,7 +126,7 @@ namespace mlx newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, nullptr); #endif - if(newBuffer.copyFromBuffer(*this)) // if the copy succeded we swap the buffers, else the new one is deleted + if(newBuffer.copyFromBuffer(*this)) // if the copy succeded we swap the buffers, otherwise the new one is deleted this->swap(newBuffer); newBuffer.destroy(); } @@ -155,6 +152,12 @@ namespace mlx VkBufferUsageFlags temp_u = _usage; _usage = buffer._usage; buffer._usage = temp_u; + + #ifdef DEBUG + std::string temp_n = _name; + _name = buffer._name; + buffer._name = temp_n; + #endif } void Buffer::flush(VkDeviceSize size, VkDeviceSize offset) diff --git a/src/renderer/command/single_time_cmd_manager.cpp b/src/renderer/command/single_time_cmd_manager.cpp index e668676..c4028d5 100644 --- a/src/renderer/command/single_time_cmd_manager.cpp +++ b/src/renderer/command/single_time_cmd_manager.cpp @@ -6,23 +6,20 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/12/15 19:57:49 by maldavid #+# #+# */ -/* Updated: 2024/01/05 20:29:01 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:30:49 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include #include -#include #include namespace mlx { - SingleTimeCmdManager::SingleTimeCmdManager() : _buffers(MIN_POOL_SIZE) {} - void SingleTimeCmdManager::init() noexcept { _pool.init(); - for(int i = 0; i < MIN_POOL_SIZE; i++) + for(int i = 0; i < BASE_POOL_SIZE; i++) { _buffers.emplace_back(); _buffers.back().init(CmdBuffer::kind::single_time, &_pool); @@ -43,6 +40,19 @@ namespace mlx return _buffers.back(); } + void SingleTimeCmdManager::updateSingleTimesCmdBuffersSubmitState() noexcept + { + for(CmdBuffer& cmd : _buffers) + cmd.updateSubmitState(); + } + + void SingleTimeCmdManager::waitForAllExecutions() noexcept + { + for(CmdBuffer& cmd : _buffers) + cmd.waitForExecution(); + } + + void SingleTimeCmdManager::destroy() noexcept { std::for_each(_buffers.begin(), _buffers.end(), [](CmdBuffer& buf) @@ -51,6 +61,4 @@ namespace mlx }); _pool.destroy(); } - - SingleTimeCmdManager::~SingleTimeCmdManager() {} } diff --git a/src/renderer/command/single_time_cmd_manager.h b/src/renderer/command/single_time_cmd_manager.h index dcbb0f8..ea7330c 100644 --- a/src/renderer/command/single_time_cmd_manager.h +++ b/src/renderer/command/single_time_cmd_manager.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/12/15 18:25:57 by maldavid #+# #+# */ -/* Updated: 2024/01/05 20:28:41 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:30:19 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,7 +14,7 @@ #define __MLX_SINGLE_TIME_CMD_MANAGER__ #include - +#include #include namespace mlx @@ -23,20 +23,23 @@ namespace mlx class SingleTimeCmdManager { + friend class Render_Core; + public: - SingleTimeCmdManager(); + SingleTimeCmdManager() = default; void init() noexcept; void destroy() noexcept; + void updateSingleTimesCmdBuffersSubmitState() noexcept; + void waitForAllExecutions() noexcept; + inline CmdPool& getCmdPool() noexcept { return _pool; } CmdBuffer& getCmdBuffer() noexcept; - ~SingleTimeCmdManager(); + ~SingleTimeCmdManager() = default; - inline static constexpr const uint8_t MIN_POOL_SIZE = 8; - - private: + inline static constexpr const uint8_t BASE_POOL_SIZE = 16; private: std::vector _buffers; diff --git a/src/renderer/command/vk_cmd_buffer.cpp b/src/renderer/command/vk_cmd_buffer.cpp index 5b38563..5ff7066 100644 --- a/src/renderer/command/vk_cmd_buffer.cpp +++ b/src/renderer/command/vk_cmd_buffer.cpp @@ -6,11 +6,12 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:26:06 by maldavid #+# #+# */ -/* Updated: 2024/01/05 23:06:04 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:07:07 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include "vk_cmd_buffer.h" +#include #include #include #include @@ -19,6 +20,21 @@ namespace mlx { + bool vector_push_back_if_not_found(std::vector& vector, CmdResource* res) + { + auto it = std::find_if(vector.begin(), vector.end(), [=](const CmdResource* vres) + { + return vres->getUUID() == res->getUUID(); + }); + + if(it == vector.end()) + { + vector.push_back(res); + return true; + } + return false; + } + void CmdBuffer::init(kind type, CmdManager* manager) { init(type, &manager->getCmdPool()); @@ -62,7 +78,7 @@ namespace mlx _state = state::recording; } - void CmdBuffer::bindVertexBuffer(Buffer& buffer) const noexcept + void CmdBuffer::bindVertexBuffer(Buffer& buffer) noexcept { if(!isRecording()) { @@ -71,10 +87,12 @@ namespace mlx } VkDeviceSize offset[] = { buffer.getOffset() }; vkCmdBindVertexBuffers(_cmd_buffer, 0, 1, &buffer.get(), offset); + buffer.recordedInCmdBuffer(); + vector_push_back_if_not_found(_cmd_resources, &buffer); } - void CmdBuffer::bindIndexBuffer(Buffer& buffer) const noexcept + void CmdBuffer::bindIndexBuffer(Buffer& buffer) noexcept { if(!isRecording()) { @@ -82,30 +100,43 @@ namespace mlx return; } vkCmdBindIndexBuffer(_cmd_buffer, buffer.get(), buffer.getOffset(), VK_INDEX_TYPE_UINT16); + buffer.recordedInCmdBuffer(); + vector_push_back_if_not_found(_cmd_resources, &buffer); } - void CmdBuffer::copyBuffer(Buffer& dst, Buffer& src) const noexcept + void CmdBuffer::copyBuffer(Buffer& dst, Buffer& src) noexcept { if(!isRecording()) { core::error::report(e_kind::warning, "Vulkan : trying to do a buffer to buffer copy in a non recording command buffer"); return; } + + preTransferBarrier(); + VkBufferCopy copyRegion{}; copyRegion.size = src.getSize(); vkCmdCopyBuffer(_cmd_buffer, src.get(), dst.get(), 1, ©Region); + + postTransferBarrier(); + dst.recordedInCmdBuffer(); src.recordedInCmdBuffer(); + vector_push_back_if_not_found(_cmd_resources, &dst); + vector_push_back_if_not_found(_cmd_resources, &src); } - void CmdBuffer::copyBufferToImage(Buffer& buffer, Image& image) const noexcept + void CmdBuffer::copyBufferToImage(Buffer& buffer, Image& image) noexcept { if(!isRecording()) { core::error::report(e_kind::warning, "Vulkan : trying to do a buffer to image copy in a non recording command buffer"); return; } + + preTransferBarrier(); + VkBufferImageCopy region{}; region.bufferOffset = 0; region.bufferRowLength = 0; @@ -119,17 +150,24 @@ namespace mlx vkCmdCopyBufferToImage(_cmd_buffer, buffer.get(), image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + postTransferBarrier(); + image.recordedInCmdBuffer(); buffer.recordedInCmdBuffer(); + vector_push_back_if_not_found(_cmd_resources, &image); + vector_push_back_if_not_found(_cmd_resources, &buffer); } - void CmdBuffer::copyImagetoBuffer(Image& image, Buffer& buffer) const noexcept + void CmdBuffer::copyImagetoBuffer(Image& image, Buffer& buffer) noexcept { if(!isRecording()) { core::error::report(e_kind::warning, "Vulkan : trying to do an image to buffer copy in a non recording command buffer"); return; } + + preTransferBarrier(); + VkBufferImageCopy region{}; region.bufferOffset = 0; region.bufferRowLength = 0; @@ -143,11 +181,15 @@ namespace mlx vkCmdCopyImageToBuffer(_cmd_buffer, image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer.get(), 1, ®ion); + postTransferBarrier(); + image.recordedInCmdBuffer(); buffer.recordedInCmdBuffer(); + vector_push_back_if_not_found(_cmd_resources, &buffer); + vector_push_back_if_not_found(_cmd_resources, &image); } - void CmdBuffer::transitionImageLayout(Image& image, VkImageLayout new_layout) const noexcept + void CmdBuffer::transitionImageLayout(Image& image, VkImageLayout new_layout) noexcept { if(!isRecording()) { @@ -176,7 +218,7 @@ namespace mlx if(barrier.oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; else if(barrier.srcAccessMask != 0) - sourceStage = accessFlagsToPipelineStage(barrier.srcAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + sourceStage = RCore::accessFlagsToPipelineStage(barrier.srcAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); else sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; @@ -184,12 +226,14 @@ namespace mlx if(barrier.newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) destinationStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; else if(barrier.dstAccessMask != 0) - destinationStage = accessFlagsToPipelineStage(barrier.dstAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + destinationStage = RCore::accessFlagsToPipelineStage(barrier.dstAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); else destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; vkCmdPipelineBarrier(_cmd_buffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); + image.recordedInCmdBuffer(); + vector_push_back_if_not_found(_cmd_resources, &image); } void CmdBuffer::endRecord() @@ -204,28 +248,28 @@ namespace mlx _state = state::idle; } - void CmdBuffer::submitIdle() noexcept + void CmdBuffer::submitIdle(bool shouldWaitForExecution) noexcept { - auto device = Render_Core::get().getDevice().get(); + if(_type != kind::single_time) + { + core::error::report(e_kind::error, "Vulkan : try to perform an idle submit on a command buffer that is not single-time, this is not allowed"); + return; + } - VkSubmitInfo submitInfo = {}; + _fence.reset(); + + VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &_cmd_buffer; - VkFenceCreateInfo fenceCreateInfo = {}; - fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - - VkFence fence; - vkCreateFence(device, &fenceCreateInfo, nullptr, &fence); - vkResetFences(device, 1, &fence); - VkResult res = vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, fence); + VkResult res = vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, _fence.get()); if(res != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit a single time command buffer, %s", RCore::verbaliseResultVk(res)); _state = state::submitted; - vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX); - vkDestroyFence(device, fence, nullptr); - _state = state::ready; + + if(shouldWaitForExecution) + waitForExecution(); } void CmdBuffer::submit(Semaphore* semaphores) noexcept @@ -245,6 +289,8 @@ namespace mlx } VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + _fence.reset(); + VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = (semaphores == nullptr ? 0 : waitSemaphores.size()); @@ -261,10 +307,46 @@ namespace mlx _state = state::submitted; } + void CmdBuffer::updateSubmitState() noexcept + { + if(!_fence.isReady()) + return; + + for(CmdResource* res : _cmd_resources) + res->removedFromCmdBuffer(); + _cmd_resources.clear(); + _state = state::ready; + } + + void CmdBuffer::preTransferBarrier() noexcept + { + VkMemoryBarrier memoryBarrier{}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memoryBarrier.pNext = nullptr; + memoryBarrier.srcAccessMask = 0U; + memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + vkCmdPipelineBarrier(_cmd_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr); + } + + void CmdBuffer::postTransferBarrier() noexcept + { + VkMemoryBarrier memoryBarrier{}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memoryBarrier.pNext = nullptr; + memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT; + + vkCmdPipelineBarrier(_cmd_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr); + } + void CmdBuffer::destroy() noexcept { _fence.destroy(); _cmd_buffer = VK_NULL_HANDLE; _state = state::uninit; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed command buffer"); + #endif } } diff --git a/src/renderer/command/vk_cmd_buffer.h b/src/renderer/command/vk_cmd_buffer.h index 421890c..d8fd7aa 100644 --- a/src/renderer/command/vk_cmd_buffer.h +++ b/src/renderer/command/vk_cmd_buffer.h @@ -6,18 +6,17 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:25:42 by maldavid #+# #+# */ -/* Updated: 2024/01/05 23:10:01 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:25:50 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef __MLX_VK_CMD_BUFFER__ #define __MLX_VK_CMD_BUFFER__ -#include #include #include #include -#include +#include namespace mlx { @@ -49,17 +48,18 @@ namespace mlx void beginRecord(VkCommandBufferUsageFlags usage = 0); void submit(class Semaphore* semaphores) noexcept; - void submitIdle() noexcept; - inline void waitForExecution() noexcept { _fence.waitAndReset(); _state = state::ready; } + void submitIdle(bool shouldWaitForExecution = true) noexcept; // TODO : handle `shouldWaitForExecution` as false by default (needs to modify CmdResources lifetimes to do so) + void updateSubmitState() noexcept; + inline void waitForExecution() noexcept { _fence.wait(); updateSubmitState(); _state = state::ready; } inline void reset() noexcept { vkResetCommandBuffer(_cmd_buffer, 0); } void endRecord(); - void bindVertexBuffer(Buffer& buffer) const noexcept; - void bindIndexBuffer(Buffer& buffer) const noexcept; - void copyBuffer(Buffer& dst, Buffer& src) const noexcept; - void copyBufferToImage(Buffer& buffer, Image& image) const noexcept; - void copyImagetoBuffer(Image& image, Buffer& buffer) const noexcept; - void transitionImageLayout(Image& image, VkImageLayout new_layout) const noexcept; + void bindVertexBuffer(Buffer& buffer) noexcept; + void bindIndexBuffer(Buffer& buffer) noexcept; + void copyBuffer(Buffer& dst, Buffer& src) noexcept; + void copyBufferToImage(Buffer& buffer, Image& image) noexcept; + void copyImagetoBuffer(Image& image, Buffer& buffer) noexcept; + void transitionImageLayout(Image& image, VkImageLayout new_layout) noexcept; inline bool isInit() const noexcept { return _state != state::uninit; } inline bool isReadyToBeUsed() const noexcept { return _state == state::ready; } @@ -72,7 +72,11 @@ namespace mlx inline Fence& getFence() noexcept { return _fence; } private: - std::unordered_set _resources; + void preTransferBarrier() noexcept; + void postTransferBarrier() noexcept; + + private: + std::vector _cmd_resources; Fence _fence; VkCommandBuffer _cmd_buffer = VK_NULL_HANDLE; class CmdPool* _pool = nullptr; diff --git a/src/renderer/core/cmd_resource.h b/src/renderer/core/cmd_resource.h index 67db160..695ae16 100644 --- a/src/renderer/core/cmd_resource.h +++ b/src/renderer/core/cmd_resource.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/12/16 20:44:29 by maldavid #+# #+# */ -/* Updated: 2024/01/05 23:12:45 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:19:10 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,6 +14,7 @@ #define __MLX_COMMAND_RESOURCE__ #include +#include namespace mlx { @@ -28,18 +29,18 @@ namespace mlx }; public: - CmdResource() = default; + CmdResource() : _uuid() {} inline void recordedInCmdBuffer() noexcept { _state = state::in_cmd_buffer; } inline void removedFromCmdBuffer() noexcept { _state = state::out_cmd_buffer; - if(_destroy_required && _destroy_required) + if(_destroy_required && _destroyer) { _destroyer(); _destroy_required = false; } } - inline void setDestroyer(func::function&& functor) { _destroyer = functor; } + inline void setDestroyer(func::function functor) { _destroyer = functor; } inline void requireDestroy() noexcept { if(_state == state::out_cmd_buffer && _destroyer) @@ -47,30 +48,15 @@ namespace mlx else _destroy_required = true; } - inline uint64_t getUUID() const noexcept { return _uuid; } + inline UUID getUUID() const noexcept { return _uuid; } virtual ~CmdResource() = default; private: - void realDestroy(); - - private: - uint64_t _uuid = 0; + UUID _uuid; state _state = state::out_cmd_buffer; func::function _destroyer; bool _destroy_required = false; }; } -namespace std -{ - template <> - struct hash - { - std::size_t operator()(const mlx::CmdResource& res) const noexcept - { - return res.getUUID(); - } - }; -} - #endif diff --git a/src/renderer/core/memory.cpp b/src/renderer/core/memory.cpp index 0604c15..89c4b62 100644 --- a/src/renderer/core/memory.cpp +++ b/src/renderer/core/memory.cpp @@ -6,7 +6,7 @@ /* By: kbz_8 +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/10/20 22:02:37 by kbz_8 #+# #+# */ -/* Updated: 2024/01/03 13:09:40 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 00:09:18 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -91,7 +91,10 @@ namespace mlx if(res != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Graphics allocator : failed to allocate a buffer, %s", RCore::verbaliseResultVk(res)); if(name != nullptr) + { + Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_BUFFER, (uint64_t)buffer, name); vmaSetAllocationName(_allocator, allocation, name); + } #ifdef DEBUG core::error::report(e_kind::message, "Graphics Allocator : created new buffer"); #endif @@ -116,7 +119,10 @@ namespace mlx if(res != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Graphics allocator : failed to allocate an image, %s", RCore::verbaliseResultVk(res)); if(name != nullptr) + { + Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_IMAGE, (uint64_t)image, name); vmaSetAllocationName(_allocator, allocation, name); + } #ifdef DEBUG core::error::report(e_kind::message, "Graphics Allocator : created new image"); #endif diff --git a/src/renderer/core/render_core.cpp b/src/renderer/core/render_core.cpp index aa3268d..ab7b9a6 100644 --- a/src/renderer/core/render_core.cpp +++ b/src/renderer/core/render_core.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/17 23:33:34 by maldavid #+# #+# */ -/* Updated: 2024/01/03 15:22:38 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:29:31 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,6 +14,7 @@ #include #include +#include #include #ifdef DEBUG @@ -75,6 +76,43 @@ namespace mlx } return nullptr; } + + VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags) + { + VkPipelineStageFlags stages = 0; + + while(accessFlags != 0) + { + VkAccessFlagBits AccessFlag = static_cast(accessFlags & (~(accessFlags - 1))); + if(AccessFlag == 0 || (AccessFlag & (AccessFlag - 1)) != 0) + core::error::report(e_kind::fatal_error, "Vulkan : an error has been caught during access flag to pipeline stage operation"); + accessFlags &= ~AccessFlag; + + switch(AccessFlag) + { + case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; break; + case VK_ACCESS_INDEX_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break; + case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break; + case VK_ACCESS_UNIFORM_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break; + case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; + case VK_ACCESS_SHADER_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break; + case VK_ACCESS_SHADER_WRITE_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break; + case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; + case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; + case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; + case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; + case VK_ACCESS_TRANSFER_READ_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; + case VK_ACCESS_TRANSFER_WRITE_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; + case VK_ACCESS_HOST_READ_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break; + case VK_ACCESS_HOST_WRITE_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break; + case VK_ACCESS_MEMORY_READ_BIT: break; + case VK_ACCESS_MEMORY_WRITE_BIT: break; + + default: core::error::report(e_kind::error, "Vulkan : unknown access flag"); break; + } + } + return stages; + } } void Render_Core::init() diff --git a/src/renderer/core/render_core.h b/src/renderer/core/render_core.h index 07e5840..0e9d8c7 100644 --- a/src/renderer/core/render_core.h +++ b/src/renderer/core/render_core.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:16:32 by maldavid #+# #+# */ -/* Updated: 2024/01/03 15:26:08 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:31:37 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -33,6 +33,7 @@ namespace mlx { std::optional findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties, bool error = true); const char* verbaliseResultVk(VkResult result); + VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags); } #ifdef DEBUG @@ -59,6 +60,7 @@ namespace mlx inline GPUallocator& getAllocator() noexcept { return _allocator; } inline ValidationLayers& getLayers() noexcept { return _layers; } inline CmdBuffer& getSingleTimeCmdBuffer() noexcept { return _cmd_manager.getCmdBuffer(); } + inline SingleTimeCmdManager& getSingleTimeCmdManager() noexcept { return _cmd_manager; } ~Render_Core() = default; diff --git a/src/renderer/core/vk_fence.cpp b/src/renderer/core/vk_fence.cpp index bad8872..2e2d5a4 100644 --- a/src/renderer/core/vk_fence.cpp +++ b/src/renderer/core/vk_fence.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/02 17:53:06 by maldavid #+# #+# */ -/* Updated: 2023/12/16 18:47:36 by maldavid ### ########.fr */ +/* Updated: 2024/01/06 16:57:26 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -49,5 +49,8 @@ namespace mlx if(_fence != VK_NULL_HANDLE) vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr); _fence = VK_NULL_HANDLE; + #ifdef DEBUG + core::error::report(e_kind::message, "Vulkan : destroyed fence"); + #endif } } diff --git a/src/renderer/core/vk_validation_layers.cpp b/src/renderer/core/vk_validation_layers.cpp index 367c1fb..684843b 100644 --- a/src/renderer/core/vk_validation_layers.cpp +++ b/src/renderer/core/vk_validation_layers.cpp @@ -6,12 +6,12 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/19 14:05:25 by maldavid #+# #+# */ -/* Updated: 2024/01/03 13:11:27 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 00:33:40 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ -#include "vk_validation_layers.h" #include "render_core.h" +#include "vulkan/vulkan_core.h" #include #include @@ -25,6 +25,16 @@ namespace mlx if constexpr(!enableValidationLayers) return; + uint32_t extensionCount; + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); + std::vector extensions(extensionCount); + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + if(!std::any_of(extensions.begin(), extensions.end(), [=](VkExtensionProperties ext) { return std::strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; })) + { + core::error::report(e_kind::warning , "Vulkan : %s not present, debug utils are disabled", VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + return; + } + VkDebugUtilsMessengerCreateInfoEXT createInfo{}; populateDebugMessengerCreateInfo(createInfo); VkResult res = createDebugUtilsMessengerEXT(&createInfo, nullptr); @@ -34,6 +44,14 @@ namespace mlx else core::error::report(e_kind::message, "Vulkan : enabled validation layers"); #endif + + real_vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkSetDebugUtilsObjectNameEXT"); + if(!real_vkSetDebugUtilsObjectNameEXT) + core::error::report(e_kind::warning, "Vulkan : failed to set up debug object names, %s", RCore::verbaliseResultVk(VK_ERROR_EXTENSION_NOT_PRESENT)); + #ifdef DEBUG + else + core::error::report(e_kind::message, "Vulkan : enabled debug object names"); + #endif } bool ValidationLayers::checkValidationLayerSupport() @@ -55,6 +73,19 @@ namespace mlx }); } + VkResult ValidationLayers::setDebugUtilsObjectNameEXT(VkObjectType object_type, uint64_t object_handle, const char* object_name) + { + if(!real_vkSetDebugUtilsObjectNameEXT) + return VK_ERROR_EXTENSION_NOT_PRESENT; + + VkDebugUtilsObjectNameInfoEXT name_info{}; + name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + name_info.objectType = object_type; + name_info.objectHandle = object_handle; + name_info.pObjectName = object_name; + return real_vkSetDebugUtilsObjectNameEXT(Render_Core::get().getDevice().get(), &name_info); + } + void ValidationLayers::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { createInfo = {}; @@ -64,7 +95,6 @@ namespace mlx createInfo.pfnUserCallback = ValidationLayers::debugCallback; } - void ValidationLayers::destroy() { if constexpr(enableValidationLayers) @@ -80,16 +110,9 @@ namespace mlx VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayers::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, [[maybe_unused]] void* pUserData) { if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) - { - std::cout << '\n'; - core::error::report(e_kind::error, std::string("Vulkan layer error: ") + pCallbackData->pMessage); - } + core::error::report(e_kind::error, pCallbackData->pMessage); else if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) - { - std::cout << '\n'; - core::error::report(e_kind::warning, std::string("Vulkan layer warning: ") + pCallbackData->pMessage); - } - + core::error::report(e_kind::warning, pCallbackData->pMessage); return VK_FALSE; } diff --git a/src/renderer/core/vk_validation_layers.h b/src/renderer/core/vk_validation_layers.h index 85eb48b..5ea19b8 100644 --- a/src/renderer/core/vk_validation_layers.h +++ b/src/renderer/core/vk_validation_layers.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/19 14:04:25 by maldavid #+# #+# */ -/* Updated: 2024/01/03 15:26:49 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 00:21:42 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,10 +22,15 @@ namespace mlx { public: ValidationLayers() = default; + void init(); + void destroy(); + bool checkValidationLayerSupport(); void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo); - void destroy(); + + VkResult setDebugUtilsObjectNameEXT(VkObjectType object_type, uint64_t object_handle, const char* object_name); + ~ValidationLayers() = default; private: @@ -35,6 +40,7 @@ namespace mlx private: VkDebugUtilsMessengerEXT _debugMessenger; + PFN_vkSetDebugUtilsObjectNameEXT real_vkSetDebugUtilsObjectNameEXT = nullptr; }; } diff --git a/src/renderer/images/vk_image.cpp b/src/renderer/images/vk_image.cpp index 79f806d..3cf0592 100644 --- a/src/renderer/images/vk_image.cpp +++ b/src/renderer/images/vk_image.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 11:59:07 by maldavid #+# #+# */ -/* Updated: 2024/01/05 23:08:47 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:17:54 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -99,55 +99,8 @@ namespace mlx return accessMask; } - VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags) - { - VkPipelineStageFlags stages = 0; - - while(accessFlags != 0) - { - VkAccessFlagBits AccessFlag = static_cast(accessFlags & (~(accessFlags - 1))); - if(AccessFlag == 0 || (AccessFlag & (AccessFlag - 1)) != 0) - core::error::report(e_kind::fatal_error, "Vulkan : an error has been caught during access flag to pipeline stage operation"); - accessFlags &= ~AccessFlag; - - switch(AccessFlag) - { - case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; break; - case VK_ACCESS_INDEX_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break; - case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break; - case VK_ACCESS_UNIFORM_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break; - case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; - case VK_ACCESS_SHADER_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break; - case VK_ACCESS_SHADER_WRITE_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break; - case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; - case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; - case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; - case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; - case VK_ACCESS_TRANSFER_READ_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; - case VK_ACCESS_TRANSFER_WRITE_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break; - case VK_ACCESS_HOST_READ_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break; - case VK_ACCESS_HOST_WRITE_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break; - case VK_ACCESS_MEMORY_READ_BIT: break; - case VK_ACCESS_MEMORY_WRITE_BIT: break; - - default: core::error::report(e_kind::error, "Vulkan : unknown access flag"); break; - } - } - return stages; - } - void Image::create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool dedicated_memory) { - CmdResource::setDestroyer([this]() - { - this->destroySampler(); - this->destroyImageView(); - - if(_image != VK_NULL_HANDLE) - Render_Core::get().getAllocator().destroyImage(_allocation, _image); - _image = VK_NULL_HANDLE; - }); - _width = width; _height = height; _format = format; @@ -177,6 +130,9 @@ namespace mlx } _allocation = Render_Core::get().getAllocator().createImage(&imageInfo, &alloc_info, _image, name); + #ifdef DEBUG + _name = name; + #endif } void Image::createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept @@ -195,6 +151,10 @@ namespace mlx VkResult res = vkCreateImageView(Render_Core::get().getDevice().get(), &viewInfo, nullptr, &_image_view); if(res != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image view, %s", RCore::verbaliseResultVk(res)); + #ifdef DEBUG + else + Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)_image_view, _name.c_str()); + #endif } void Image::createSampler() noexcept @@ -214,7 +174,11 @@ namespace mlx VkResult res = vkCreateSampler(Render_Core::get().getDevice().get(), &info, nullptr, &_sampler); if(res != VK_SUCCESS) - core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image, %s", RCore::verbaliseResultVk(res)); + core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image sampler, %s", RCore::verbaliseResultVk(res)); + #ifdef DEBUG + else + Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_SAMPLER, (uint64_t)_sampler, _name.c_str()); + #endif } void Image::copyFromBuffer(Buffer& buffer) @@ -287,6 +251,16 @@ namespace mlx void Image::destroy() noexcept { + // not creating destroyer in `create` as some image may be copied (and so `this` will be invalid) + CmdResource::setDestroyer([this]() + { + destroySampler(); + destroyImageView(); + + if(_image != VK_NULL_HANDLE) + Render_Core::get().getAllocator().destroyImage(_allocation, _image); + _image = VK_NULL_HANDLE; + }); CmdResource::requireDestroy(); } diff --git a/src/renderer/images/vk_image.h b/src/renderer/images/vk_image.h index 3349112..ddd9948 100644 --- a/src/renderer/images/vk_image.h +++ b/src/renderer/images/vk_image.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 11:54:21 by maldavid #+# #+# */ -/* Updated: 2024/01/05 22:36:58 by maldavid ### ########.fr */ +/* Updated: 2024/01/07 01:20:31 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,10 @@ #include #include +#ifdef DEBUG + #include +#endif + namespace mlx { uint32_t formatSize(VkFormat format); @@ -29,7 +33,6 @@ namespace mlx bool isDepthFormat(VkFormat format); VkFormat bitsToFormat(uint32_t bits); VkPipelineStageFlags layoutToAccessMask(VkImageLayout layout, bool isDestination); - VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags); class Image : public CmdResource { @@ -76,6 +79,9 @@ namespace mlx VkImage _image = VK_NULL_HANDLE; VkImageView _image_view = VK_NULL_HANDLE; VkSampler _sampler = VK_NULL_HANDLE; + #ifdef DEBUG + std::string _name; + #endif VkFormat _format; VkImageTiling _tiling; VkImageLayout _layout = VK_IMAGE_LAYOUT_UNDEFINED; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 2a57b20..0c9ff75 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 17:25:16 by maldavid #+# #+# */ -/* Updated: 2023/12/24 16:04:04 by kbz_8 ### ########.fr */ +/* Updated: 2024/01/07 01:00:18 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -150,7 +150,7 @@ namespace mlx } else { - _cmd.getCmdBuffer(_current_frame_index).submitIdle(); + _cmd.getCmdBuffer(_current_frame_index).submitIdle(true); _current_frame_index = 0; } }