From 19ccc1230efa5d89d80d833d64e48a4f468a3a83 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 18 Nov 2023 17:25:30 +0100 Subject: [PATCH] cleaning renderpass, framebuffers and swapchain code, setting all vulkan resources to NULL after destroy --- src/core/application.h | 4 +- src/renderer/command/vk_cmd_pool.cpp | 3 +- src/renderer/core/vk_device.cpp | 3 +- src/renderer/core/vk_fence.cpp | 6 +- src/renderer/core/vk_instance.cpp | 3 +- src/renderer/core/vk_semaphore.cpp | 4 +- src/renderer/core/vk_surface.cpp | 3 +- .../descriptors/vk_descriptor_pool.cpp | 3 +- .../descriptors/vk_descriptor_set_layout.cpp | 3 +- src/renderer/images/vk_image.cpp | 188 ++++++++++++++- src/renderer/images/vk_image.h | 24 +- src/renderer/pipeline/pipeline.cpp | 8 +- src/renderer/renderer.cpp | 46 ++-- src/renderer/renderer.h | 12 +- .../vk_framebuffer.cpp | 17 +- .../vk_framebuffer.h | 26 ++- .../vk_render_pass.cpp | 21 +- .../vk_render_pass.h | 9 +- src/renderer/swapchain/vk_imageview.cpp | 47 ---- src/renderer/swapchain/vk_imageview.h | 34 --- src/renderer/swapchain/vk_swapchain.cpp | 214 +++++++++--------- src/renderer/swapchain/vk_swapchain.h | 47 ++-- test/main.c | 9 +- 23 files changed, 435 insertions(+), 299 deletions(-) rename src/renderer/{swapchain => renderpass}/vk_framebuffer.cpp (78%) rename src/renderer/{swapchain => renderpass}/vk_framebuffer.h (61%) rename src/renderer/{swapchain => renderpass}/vk_render_pass.cpp (82%) rename src/renderer/{swapchain => renderpass}/vk_render_pass.h (86%) delete mode 100644 src/renderer/swapchain/vk_imageview.cpp delete mode 100644 src/renderer/swapchain/vk_imageview.h diff --git a/src/core/application.h b/src/core/application.h index 6ae3e88..96c3373 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 21:49:46 by maldavid #+# #+# */ -/* Updated: 2023/08/28 10:19:35 by maldavid ### ########.fr */ +/* Updated: 2023/11/17 11:57:42 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -55,7 +55,7 @@ namespace mlx::core inline void loopHook(int (*f)(void*), void* param); inline void loopEnd() noexcept; - + void run() noexcept; ~Application(); diff --git a/src/renderer/command/vk_cmd_pool.cpp b/src/renderer/command/vk_cmd_pool.cpp index 86eacf9..f78538f 100644 --- a/src/renderer/command/vk_cmd_pool.cpp +++ b/src/renderer/command/vk_cmd_pool.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:24:33 by maldavid #+# #+# */ -/* Updated: 2022/12/18 22:56:26 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:23:38 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -29,5 +29,6 @@ namespace mlx void CmdPool::destroy() noexcept { vkDestroyCommandPool(Render_Core::get().getDevice().get(), _cmd_pool, nullptr); + _cmd_pool = VK_NULL_HANDLE; } } diff --git a/src/renderer/core/vk_device.cpp b/src/renderer/core/vk_device.cpp index e0d89d5..08ed842 100644 --- a/src/renderer/core/vk_device.cpp +++ b/src/renderer/core/vk_device.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:14:29 by maldavid #+# #+# */ -/* Updated: 2023/11/11 10:38:01 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:22:02 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -154,5 +154,6 @@ namespace mlx void Device::destroy() noexcept { vkDestroyDevice(_device, nullptr); + _device = VK_NULL_HANDLE; } } diff --git a/src/renderer/core/vk_fence.cpp b/src/renderer/core/vk_fence.cpp index 8fd23d8..6ecb821 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/11/08 20:14:23 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:07:21 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -42,6 +42,8 @@ namespace mlx void Fence::destroy() noexcept { - vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr); + if(_fence != VK_NULL_HANDLE) + vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr); + _fence = VK_NULL_HANDLE; } } diff --git a/src/renderer/core/vk_instance.cpp b/src/renderer/core/vk_instance.cpp index 5c1e462..226505c 100644 --- a/src/renderer/core/vk_instance.cpp +++ b/src/renderer/core/vk_instance.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:04:21 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:13:30 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:21:42 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -88,5 +88,6 @@ namespace mlx void Instance::destroy() noexcept { vkDestroyInstance(_instance, nullptr); + _instance = VK_NULL_HANDLE; } } diff --git a/src/renderer/core/vk_semaphore.cpp b/src/renderer/core/vk_semaphore.cpp index 4a2f195..00f2b07 100644 --- a/src/renderer/core/vk_semaphore.cpp +++ b/src/renderer/core/vk_semaphore.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:01:08 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:14:36 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:22:29 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,6 +32,8 @@ namespace mlx void Semaphore::destroy() noexcept { vkDestroySemaphore(Render_Core::get().getDevice().get(), _renderFinishedSemaphores, nullptr); + _renderFinishedSemaphores = VK_NULL_HANDLE; vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores, nullptr); + _imageAvailableSemaphores = VK_NULL_HANDLE; } } diff --git a/src/renderer/core/vk_surface.cpp b/src/renderer/core/vk_surface.cpp index 08cb173..fdc027c 100644 --- a/src/renderer/core/vk_surface.cpp +++ b/src/renderer/core/vk_surface.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 18:58:49 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:14:48 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:22:38 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,5 +41,6 @@ namespace mlx void Surface::destroy() noexcept { vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), _surface, nullptr); + _surface = VK_NULL_HANDLE; } } diff --git a/src/renderer/descriptors/vk_descriptor_pool.cpp b/src/renderer/descriptors/vk_descriptor_pool.cpp index 54d25db..95e2f6e 100644 --- a/src/renderer/descriptors/vk_descriptor_pool.cpp +++ b/src/renderer/descriptors/vk_descriptor_pool.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/23 18:34:23 by maldavid #+# #+# */ -/* Updated: 2023/01/23 18:44:51 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:23:05 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -30,5 +30,6 @@ namespace mlx void DescriptorPool::destroy() noexcept { vkDestroyDescriptorPool(Render_Core::get().getDevice().get(), _pool, nullptr); + _pool = VK_NULL_HANDLE; } } diff --git a/src/renderer/descriptors/vk_descriptor_set_layout.cpp b/src/renderer/descriptors/vk_descriptor_set_layout.cpp index 0726c24..eec18a0 100644 --- a/src/renderer/descriptors/vk_descriptor_set_layout.cpp +++ b/src/renderer/descriptors/vk_descriptor_set_layout.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/23 18:37:28 by maldavid #+# #+# */ -/* Updated: 2023/03/31 16:37:09 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:23:16 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,5 +41,6 @@ namespace mlx void DescriptorSetLayout::destroy() noexcept { vkDestroyDescriptorSetLayout(Render_Core::get().getDevice().get(), _layout, nullptr); + _layout = VK_NULL_HANDLE; } } diff --git a/src/renderer/images/vk_image.cpp b/src/renderer/images/vk_image.cpp index c5a595c..ddd6315 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: 2023/11/14 09:31:39 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:21:14 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,6 +18,124 @@ namespace mlx { + bool isStencilFormat(VkFormat format) + { + switch(format) + { + case VK_FORMAT_D32_SFLOAT_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + return true; + + default: return false; + } + } + + bool isDepthFormat(VkFormat format) + { + switch(format) + { + case VK_FORMAT_D16_UNORM: + case VK_FORMAT_D32_SFLOAT: + case VK_FORMAT_D32_SFLOAT_S8_UINT: + case VK_FORMAT_D24_UNORM_S8_UINT: + case VK_FORMAT_D16_UNORM_S8_UINT: + return true; + + default: return false; + } + } + + VkFormat bitsToFormat(uint32_t bits) + { + switch(bits) + { + case 8: return VK_FORMAT_R8_UNORM; + case 16: return VK_FORMAT_R8G8_UNORM; + case 24: return VK_FORMAT_R8G8B8_UNORM; + case 32: return VK_FORMAT_R8G8B8A8_UNORM; + case 48: return VK_FORMAT_R16G16B16_SFLOAT; + case 64: return VK_FORMAT_R16G16B16A16_SFLOAT; + case 96: return VK_FORMAT_R32G32B32_SFLOAT; + case 128: return VK_FORMAT_R32G32B32A32_SFLOAT; + + default: + core::error::report(e_kind::fatal_error, "Vulkan : unsupported image bit-depth"); + return VK_FORMAT_R8G8B8A8_UNORM; + } + } + + VkPipelineStageFlags layoutToAccessMask(VkImageLayout layout, bool isDestination) + { + VkPipelineStageFlags accessMask = 0; + + switch(layout) + { + case VK_IMAGE_LAYOUT_UNDEFINED: + if(isDestination) + core::error::report(e_kind::error, "Vulkan : the new layout used in a transition must not be VK_IMAGE_LAYOUT_UNDEFINED"); + break; + case VK_IMAGE_LAYOUT_GENERAL: accessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; break; + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: accessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + accessMask = VK_ACCESS_SHADER_READ_BIT; // VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: accessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: accessMask = VK_ACCESS_TRANSFER_READ_BIT; break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: accessMask = VK_ACCESS_TRANSFER_WRITE_BIT; break; + case VK_IMAGE_LAYOUT_PREINITIALIZED: + if(!isDestination) + accessMask = VK_ACCESS_HOST_WRITE_BIT; + else + core::error::report(e_kind::error, "Vulkan : the new layout used in a transition must not be VK_IMAGE_LAYOUT_PREINITIALIZED"); + break; + case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; break; + case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; break; + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: accessMask = VK_ACCESS_MEMORY_READ_BIT; break; + + default: core::error::report(e_kind::error, "Vulkan : unexpected image layout"); break; + } + + 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) { _width = width; @@ -193,19 +311,79 @@ namespace mlx _transfer_cmd.submitIdle(); } - void Image::destroy() noexcept + void Image::transitionLayout(VkImageLayout new_layout) + { + if(new_layout == _layout) + return; + + if(!_transfer_cmd.isInit()) + _transfer_cmd.init(&_pool); + _transfer_cmd.reset(); + _transfer_cmd.beginRecord(); + + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = _layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = _image; + barrier.subresourceRange.aspectMask = isDepthFormat(_format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.srcAccessMask = layoutToAccessMask(_layout, false); + barrier.dstAccessMask = layoutToAccessMask(new_layout, true); + if(isStencilFormat(_format)) + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + + VkPipelineStageFlags sourceStage = 0; + 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); + else + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + + VkPipelineStageFlags destinationStage = 0; + 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); + else + destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + + vkCmdPipelineBarrier(_transfer_cmd.get(), sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); + + _transfer_cmd.endRecord(); + _transfer_cmd.submitIdle(); + _layout = new_layout; + } + + void Image::destroySampler() noexcept { if(_sampler != VK_NULL_HANDLE) vkDestroySampler(Render_Core::get().getDevice().get(), _sampler, nullptr); + _sampler = VK_NULL_HANDLE; + } + + void Image::destroyImageView() noexcept + { if(_image_view != VK_NULL_HANDLE) vkDestroyImageView(Render_Core::get().getDevice().get(), _image_view, nullptr); + _image_view = VK_NULL_HANDLE; + } + + void Image::destroy() noexcept + { + destroySampler(); + destroyImageView(); + destroyCmdPool(); if(_image != VK_NULL_HANDLE) Render_Core::get().getAllocator().destroyImage(_allocation, _image); _image = VK_NULL_HANDLE; - if(_transfer_cmd.isInit()) - _transfer_cmd.destroy(); - _pool.destroy(); } uint32_t formatSize(VkFormat format) diff --git a/src/renderer/images/vk_image.h b/src/renderer/images/vk_image.h index 22f4924..8fba630 100644 --- a/src/renderer/images/vk_image.h +++ b/src/renderer/images/vk_image.h @@ -6,12 +6,12 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 11:54:21 by maldavid #+# #+# */ -/* Updated: 2023/11/14 03:15:18 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:10:05 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef __VK_IMAGE__ -#define __VK_IMAGE__ +#ifndef __MLX_VK_IMAGE__ +#define __MLX_VK_IMAGE__ #include #include @@ -25,14 +25,26 @@ namespace mlx class Image { + friend class SwapChain; + public: Image() = default; + inline void create(VkImage image, VkFormat format, uint32_t width, uint32_t height, VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED) noexcept + { + _image = image; + _format = format; + _width = width; + _height = height; + _layout = layout; + _pool.init(); + } void create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool decated_memory = false); void createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept; void createSampler() noexcept; void copyFromBuffer(class Buffer& buffer); void copyToBuffer(class Buffer& buffer); + void transitionLayout(VkImageLayout new_layout); virtual void destroy() noexcept; inline VkImage get() noexcept { return _image; } @@ -46,6 +58,11 @@ namespace mlx virtual ~Image() = default; + private: + void destroySampler() noexcept; + void destroyImageView() noexcept; + inline void destroyCmdPool() noexcept { _transfer_cmd.destroy(); _pool.destroy(); } + private: CmdBuffer _transfer_cmd; CmdPool _pool; @@ -55,6 +72,7 @@ namespace mlx VkSampler _sampler = VK_NULL_HANDLE; VkFormat _format; VkImageTiling _tiling; + VkImageLayout _layout = VK_IMAGE_LAYOUT_UNDEFINED; uint32_t _width = 0; uint32_t _height = 0; }; diff --git a/src/renderer/pipeline/pipeline.cpp b/src/renderer/pipeline/pipeline.cpp index 2aeb9ea..bd8ef36 100644 --- a/src/renderer/pipeline/pipeline.cpp +++ b/src/renderer/pipeline/pipeline.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 21:27:38 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:36:18 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 16:57:57 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -222,14 +222,14 @@ namespace mlx VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float)renderer.getSwapChain()._swapChainExtent.width; - viewport.height = (float)renderer.getSwapChain()._swapChainExtent.height; + viewport.width = (float)renderer.getSwapChain().getExtent().width; + viewport.height = (float)renderer.getSwapChain().getExtent().height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor{}; scissor.offset = { 0, 0 }; - scissor.extent = renderer.getSwapChain()._swapChainExtent; + scissor.extent = renderer.getSwapChain().getExtent(); VkPipelineViewportStateCreateInfo viewportState{}; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index b830e68..2225180 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/11/16 13:48:42 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:08:19 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,9 +20,11 @@ namespace mlx { _surface.create(*this); _swapchain.init(this); - _pass.init(this); - _swapchain.initFB(); + _pass.init(_swapchain.getImagesFormat()); _cmd.init(); + + for(int i = 0; i < _swapchain.getImagesNumber(); i++) + _framebuffers.emplace_back().init(_pass, _swapchain.getImage(i)); for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) _semaphores[i].init(); @@ -55,15 +57,15 @@ namespace mlx _framebufferResized = false; } - + bool Renderer::beginFrame() { auto device = Render_Core::get().getDevice().get(); - _cmd.getCmdBuffer(_active_image_index).waitForExecution(); - _cmd.getCmdBuffer(_active_image_index).reset(); + _cmd.getCmdBuffer(_current_frame_index).waitForExecution(); + _cmd.getCmdBuffer(_current_frame_index).reset(); - VkResult result = vkAcquireNextImageKHR(device, _swapchain(), UINT64_MAX, _semaphores[_active_image_index].getImageSemaphore(), VK_NULL_HANDLE, &_image_index); + VkResult result = vkAcquireNextImageKHR(device, _swapchain(), UINT64_MAX, _semaphores[_current_frame_index].getImageSemaphore(), VK_NULL_HANDLE, &_image_index); if(result == VK_ERROR_OUT_OF_DATE_KHR) { @@ -73,36 +75,37 @@ namespace mlx else if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) core::error::report(e_kind::fatal_error, "Vulkan error : failed to acquire swapchain image"); - _cmd.getCmdBuffer(_active_image_index).beginRecord(); - _pass.begin(); + _cmd.getCmdBuffer(_current_frame_index).beginRecord(); + auto& fb = _framebuffers[_image_index]; + _pass.begin(getActiveCmdBuffer(), fb); - _pipeline.bindPipeline(_cmd.getCmdBuffer(_active_image_index)); + _pipeline.bindPipeline(_cmd.getCmdBuffer(_current_frame_index)); VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float)_swapchain._swapChainExtent.width; - viewport.height = (float)_swapchain._swapChainExtent.height; + viewport.width = static_cast(fb.getWidth()); + viewport.height = static_cast(fb.getHeight()); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; - vkCmdSetViewport(_cmd.getCmdBuffer(_active_image_index).get(), 0, 1, &viewport); + vkCmdSetViewport(_cmd.getCmdBuffer(_current_frame_index).get(), 0, 1, &viewport); VkRect2D scissor{}; scissor.offset = { 0, 0 }; - scissor.extent = _swapchain._swapChainExtent; - vkCmdSetScissor(_cmd.getCmdBuffer(_active_image_index).get(), 0, 1, &scissor); + scissor.extent = _swapchain.getExtent(); + vkCmdSetScissor(_cmd.getCmdBuffer(_current_frame_index).get(), 0, 1, &scissor); return true; } void Renderer::endFrame() { - _pass.end(); - _cmd.getCmdBuffer(_active_image_index).endRecord(); - _cmd.getCmdBuffer(_active_image_index).submit(_semaphores[_active_image_index]); + _pass.end(getActiveCmdBuffer()); + _cmd.getCmdBuffer(_current_frame_index).endRecord(); + _cmd.getCmdBuffer(_current_frame_index).submit(_semaphores[_current_frame_index]); VkSwapchainKHR swapchain = _swapchain(); - VkSemaphore signalSemaphores[] = { _semaphores[_active_image_index].getRenderImageSemaphore() }; + VkSemaphore signalSemaphores[] = { _semaphores[_current_frame_index].getRenderImageSemaphore() }; VkPresentInfoKHR presentInfo{}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; @@ -122,7 +125,7 @@ namespace mlx else if(result != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan error : failed to present swap chain image"); - _active_image_index = (_active_image_index + 1) % MAX_FRAMES_IN_FLIGHT; + _current_frame_index = (_current_frame_index + 1) % MAX_FRAMES_IN_FLIGHT; } void Renderer::destroy() @@ -135,9 +138,10 @@ namespace mlx _frag_layout.destroy(); _cmd.destroy(); _desc_pool.destroy(); - _swapchain.destroyFB(); _pass.destroy(); _swapchain.destroy(); + for(auto& fb : _framebuffers) + fb.destroy(); for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) _semaphores[i].destroy(); _surface.destroy(); diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 1a6231d..97d59bc 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 17:14:45 by maldavid #+# #+# */ -/* Updated: 2023/04/11 12:33:33 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 16:56:09 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -99,12 +100,12 @@ namespace mlx inline RenderPass& getRenderPass() noexcept { return _pass; } inline GraphicPipeline& getPipeline() noexcept { return _pipeline; } inline CmdBuffer& getCmdBuffer(int i) noexcept { return _cmd.getCmdBuffer(i); } - inline CmdBuffer& getActiveCmdBuffer() noexcept { return _cmd.getCmdBuffer(_active_image_index); } + inline CmdBuffer& getActiveCmdBuffer() noexcept { return _cmd.getCmdBuffer(_current_frame_index); } inline DescriptorSet& getVertDescriptorSet() noexcept { return _vert_set; } inline DescriptorSet& getFragDescriptorSet() noexcept { return _frag_set; } inline DescriptorSetLayout& getVertDescriptorSetLayout() noexcept { return _vert_layout; } inline DescriptorSetLayout& getFragDescriptorSetLayout() noexcept { return _frag_layout; } - inline uint32_t getActiveImageIndex() noexcept { return _active_image_index; } + inline uint32_t getActiveImageIndex() noexcept { return _current_frame_index; } inline uint32_t getImageIndex() noexcept { return _image_index; } constexpr inline void requireFrameBufferResize(int index) noexcept { _framebufferResized = true; } @@ -118,6 +119,7 @@ namespace mlx Surface _surface; SwapChain _swapchain; std::array _semaphores; + std::vector _framebuffers; DescriptorPool _desc_pool; @@ -131,7 +133,7 @@ namespace mlx class MLX_Window* _window = nullptr; - uint32_t _active_image_index = 0; + uint32_t _current_frame_index = 0; uint32_t _image_index = 0; bool _framebufferResized = false; }; diff --git a/src/renderer/swapchain/vk_framebuffer.cpp b/src/renderer/renderpass/vk_framebuffer.cpp similarity index 78% rename from src/renderer/swapchain/vk_framebuffer.cpp rename to src/renderer/renderpass/vk_framebuffer.cpp index 3451c7d..b9e2efa 100644 --- a/src/renderer/swapchain/vk_framebuffer.cpp +++ b/src/renderer/renderpass/vk_framebuffer.cpp @@ -6,27 +6,31 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:18:06 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:36:54 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:20:23 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include #include #include +#include namespace mlx { - void FrameBuffer::init(Renderer& renderer, ImageView& image) + void FrameBuffer::init(RenderPass& renderpass, Image& image) { - VkImageView attachments[] = { image() }; + VkImageView attachments[] = { image.getImageView() }; + + _width = image.getWidth(); + _height = image.getHeight(); VkFramebufferCreateInfo framebufferInfo{}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderer.getRenderPass().get(); + framebufferInfo.renderPass = renderpass.get(); framebufferInfo.attachmentCount = 1; framebufferInfo.pAttachments = attachments; - framebufferInfo.width = renderer.getSwapChain()._swapChainExtent.width; - framebufferInfo.height = renderer.getSwapChain()._swapChainExtent.height; + framebufferInfo.width = _width; + framebufferInfo.height = _height; framebufferInfo.layers = 1; if(vkCreateFramebuffer(Render_Core::get().getDevice().get(), &framebufferInfo, nullptr, &_framebuffer) != VK_SUCCESS) @@ -39,5 +43,6 @@ namespace mlx void FrameBuffer::destroy() noexcept { vkDestroyFramebuffer(Render_Core::get().getDevice().get(), _framebuffer, nullptr); + _framebuffer = VK_NULL_HANDLE; } } diff --git a/src/renderer/swapchain/vk_framebuffer.h b/src/renderer/renderpass/vk_framebuffer.h similarity index 61% rename from src/renderer/swapchain/vk_framebuffer.h rename to src/renderer/renderpass/vk_framebuffer.h index 9369103..ac1d3c5 100644 --- a/src/renderer/swapchain/vk_framebuffer.h +++ b/src/renderer/renderpass/vk_framebuffer.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:19:44 by maldavid #+# #+# */ -/* Updated: 2022/12/18 19:53:00 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 16:44:16 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,18 +17,22 @@ namespace mlx { - class FrameBuffer - { - public: - void init(class Renderer& renderer, class ImageView& image); - void destroy() noexcept; + class FrameBuffer + { + public: + void init(class RenderPass& renderpass, class Image& image); + void destroy() noexcept; - inline VkFramebuffer& operator()() noexcept { return _framebuffer; } - inline VkFramebuffer& get() noexcept { return _framebuffer; } + inline VkFramebuffer& operator()() noexcept { return _framebuffer; } + inline VkFramebuffer& get() noexcept { return _framebuffer; } + inline uint32_t getWidth() const noexcept { return _width; } + inline uint32_t getHeight() const noexcept { return _height; } - private: - VkFramebuffer _framebuffer = VK_NULL_HANDLE; - }; + private: + VkFramebuffer _framebuffer = VK_NULL_HANDLE; + uint32_t _width = 0; + uint32_t _height = 0; + }; } #endif // __MLX_VK_FRAMEBUFFER__ diff --git a/src/renderer/swapchain/vk_render_pass.cpp b/src/renderer/renderpass/vk_render_pass.cpp similarity index 82% rename from src/renderer/swapchain/vk_render_pass.cpp rename to src/renderer/renderpass/vk_render_pass.cpp index 3b18090..2eea756 100644 --- a/src/renderer/swapchain/vk_render_pass.cpp +++ b/src/renderer/renderpass/vk_render_pass.cpp @@ -6,24 +6,23 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:21:36 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:37:32 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 15:58:26 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include "vk_render_pass.h" #include #include +#include namespace mlx { static const VkClearValue clearColor = { 0.0f, 0.0f, 0.0f, 1.0f }; - void RenderPass::init(Renderer* renderer) + void RenderPass::init(VkFormat attachement_format) { - _renderer = renderer; - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = renderer->getSwapChain()._swapChainImageFormat; + colorAttachment.format = attachement_format; colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -55,7 +54,7 @@ namespace mlx #endif } - void RenderPass::begin() + void RenderPass::begin(class CmdBuffer& cmd, class FrameBuffer& fb) { if(_is_running) return; @@ -63,23 +62,23 @@ namespace mlx VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.renderPass = _renderPass; - renderPassInfo.framebuffer = _renderer->getSwapChain()._framebuffers[_renderer->getImageIndex()].get(); + renderPassInfo.framebuffer = fb.get(); renderPassInfo.renderArea.offset = { 0, 0 }; - renderPassInfo.renderArea.extent = _renderer->getSwapChain()._swapChainExtent; + renderPassInfo.renderArea.extent = { fb.getWidth(), fb.getHeight() }; renderPassInfo.clearValueCount = 1; renderPassInfo.pClearValues = &clearColor; - vkCmdBeginRenderPass(_renderer->getActiveCmdBuffer().get(), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBeginRenderPass(cmd.get(), &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); _is_running = true; } - void RenderPass::end() + void RenderPass::end(class CmdBuffer& cmd) { if(!_is_running) return; - vkCmdEndRenderPass(_renderer->getActiveCmdBuffer().get()); + vkCmdEndRenderPass(cmd.get()); _is_running = false; } diff --git a/src/renderer/swapchain/vk_render_pass.h b/src/renderer/renderpass/vk_render_pass.h similarity index 86% rename from src/renderer/swapchain/vk_render_pass.h rename to src/renderer/renderpass/vk_render_pass.h index ac23705..65bfdea 100644 --- a/src/renderer/swapchain/vk_render_pass.h +++ b/src/renderer/renderpass/vk_render_pass.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:22:00 by maldavid #+# #+# */ -/* Updated: 2022/12/18 20:33:28 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 15:58:12 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,18 +20,17 @@ namespace mlx class RenderPass { public: - void init(class Renderer* renderer); + void init(VkFormat attachement_format); void destroy() noexcept; - void begin(); - void end(); + void begin(class CmdBuffer& cmd, class FrameBuffer& fb); + void end(class CmdBuffer& cmd); inline VkRenderPass& operator()() noexcept { return _renderPass; } inline VkRenderPass& get() noexcept { return _renderPass; } private: VkRenderPass _renderPass = VK_NULL_HANDLE; - class Renderer* _renderer = nullptr; bool _is_running = false; }; } diff --git a/src/renderer/swapchain/vk_imageview.cpp b/src/renderer/swapchain/vk_imageview.cpp deleted file mode 100644 index 03dcbcc..0000000 --- a/src/renderer/swapchain/vk_imageview.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* vk_imageview.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: maldavid +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2022/10/06 18:20:49 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:37:17 by maldavid ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "vk_swapchain.h" -#include "vk_imageview.h" -#include - -namespace mlx -{ - void ImageView::init(SwapChain& swapchain, VkImage& image) - { - VkImageViewCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - createInfo.image = image; - createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - createInfo.format = swapchain._swapChainImageFormat; - createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - createInfo.subresourceRange.baseMipLevel = 0; - createInfo.subresourceRange.levelCount = 1; - createInfo.subresourceRange.baseArrayLayer = 0; - createInfo.subresourceRange.layerCount = 1; - - if(vkCreateImageView(Render_Core::get().getDevice().get(), &createInfo, nullptr, &_image) != VK_SUCCESS) - core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image view"); - #ifdef DEBUG - core::error::report(e_kind::message, "Vulkan : created new swapchain image view"); - #endif - } - - void ImageView::destroy() noexcept - { - vkDestroyImageView(Render_Core::get().getDevice().get(), _image, nullptr); - } -} diff --git a/src/renderer/swapchain/vk_imageview.h b/src/renderer/swapchain/vk_imageview.h deleted file mode 100644 index c1be288..0000000 --- a/src/renderer/swapchain/vk_imageview.h +++ /dev/null @@ -1,34 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* vk_imageview.h :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: maldavid +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2022/10/06 18:20:19 by maldavid #+# #+# */ -/* Updated: 2022/12/18 19:54:44 by maldavid ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef __MLX_VK_IMAGE_VIEW__ -#define __MLX_VK_IMAGE_VIEW__ - -#include - -namespace mlx -{ - class ImageView - { - public: - void init(class SwapChain& swapchain, VkImage& image); - void destroy() noexcept; - - inline VkImageView& operator()() noexcept { return _image; } - inline VkImageView& get() noexcept { return _image; } - - private: - VkImageView _image = VK_NULL_HANDLE; - }; -} - -#endif // __MLX_VK_IMAGE_VIEW__ diff --git a/src/renderer/swapchain/vk_swapchain.cpp b/src/renderer/swapchain/vk_swapchain.cpp index ce84222..626d305 100644 --- a/src/renderer/swapchain/vk_swapchain.cpp +++ b/src/renderer/swapchain/vk_swapchain.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:22:28 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:37:53 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:15:10 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,141 +18,137 @@ namespace mlx { - void SwapChain::init(Renderer* renderer) - { + void SwapChain::init(Renderer* renderer) + { + VkDevice device = Render_Core::get().getDevice().get(); + _renderer = renderer; + _swapChainSupport = querySwapChainSupport(Render_Core::get().getDevice().getPhysicalDevice()); - _swapChainSupport = querySwapChainSupport(Render_Core::get().getDevice().getPhysicalDevice()); + VkSurfaceFormatKHR surfaceFormat = renderer->getSurface().chooseSwapSurfaceFormat(_swapChainSupport.formats); + VkPresentModeKHR presentMode = chooseSwapPresentMode(_swapChainSupport.presentModes); + _extent = chooseSwapExtent(_swapChainSupport.capabilities); - VkSurfaceFormatKHR surfaceFormat = renderer->getSurface().chooseSwapSurfaceFormat(_swapChainSupport.formats); - VkPresentModeKHR presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; // change this to set vsync (if the driver supports it) - VkExtent2D extent = chooseSwapExtent(_swapChainSupport.capabilities); + uint32_t imageCount = _swapChainSupport.capabilities.minImageCount + 1; + if(_swapChainSupport.capabilities.maxImageCount > 0 && imageCount > _swapChainSupport.capabilities.maxImageCount) + imageCount = _swapChainSupport.capabilities.maxImageCount; - uint32_t imageCount = _swapChainSupport.capabilities.minImageCount + 1; - if(_swapChainSupport.capabilities.maxImageCount > 0 && imageCount > _swapChainSupport.capabilities.maxImageCount) - imageCount = _swapChainSupport.capabilities.maxImageCount; + Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(Render_Core::get().getDevice().getPhysicalDevice(), renderer->getSurface().get()); + uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() }; - VkSwapchainCreateInfoKHR createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = renderer->getSurface().get(); - - createInfo.minImageCount = imageCount; - createInfo.imageFormat = surfaceFormat.format; - createInfo.imageColorSpace = surfaceFormat.colorSpace; - createInfo.imageExtent = extent; - createInfo.imageArrayLayers = 1; - createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(Render_Core::get().getDevice().getPhysicalDevice(), renderer->getSurface().get()); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; - - if(indices.graphicsFamily != indices.presentFamily) + VkSwapchainCreateInfoKHR createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = renderer->getSurface().get(); + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = _extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + createInfo.preTransform = _swapChainSupport.capabilities.currentTransform; + createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = VK_NULL_HANDLE; + if(indices.graphicsFamily != indices.presentFamily) { - createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - createInfo.queueFamilyIndexCount = 2; - createInfo.pQueueFamilyIndices = queueFamilyIndices; - } + createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + createInfo.queueFamilyIndexCount = 2; + createInfo.pQueueFamilyIndices = queueFamilyIndices; + } else - createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.preTransform = _swapChainSupport.capabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - createInfo.presentMode = presentMode; - createInfo.clipped = VK_TRUE; + if(vkCreateSwapchainKHR(device, &createInfo, nullptr, &_swapChain) != VK_SUCCESS) + core::error::report(e_kind::fatal_error, "Vulkan : failed to create the swapchain"); - createInfo.oldSwapchain = VK_NULL_HANDLE; + std::vector tmp; + vkGetSwapchainImagesKHR(device, _swapChain, &imageCount, nullptr); + _images.resize(imageCount); + tmp.resize(imageCount); + vkGetSwapchainImagesKHR(device, _swapChain, &imageCount, tmp.data()); - VkDevice device = Render_Core::get().getDevice().get(); + for(int i = 0; i < imageCount; i++) + { + _images[i].create(tmp[i], surfaceFormat.format, _extent.width, _extent.height); + _images[i].transitionLayout(VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + _images[i].createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); + } - if(vkCreateSwapchainKHR(device, &createInfo, nullptr, &_swapChain) != VK_SUCCESS) - core::error::report(e_kind::fatal_error, "Vulkan : failed to create swapchain"); + _swapChainImageFormat = surfaceFormat.format; #ifdef DEBUG core::error::report(e_kind::message, "Vulkan : created new swapchain"); #endif + } - vkGetSwapchainImagesKHR(device, _swapChain, &imageCount, nullptr); - _swapChainImages.resize(imageCount); - vkGetSwapchainImagesKHR(device, _swapChain, &imageCount, _swapChainImages.data()); + SwapChain::SwapChainSupportDetails SwapChain::querySwapChainSupport(VkPhysicalDevice device) + { + SwapChain::SwapChainSupportDetails details; + VkSurfaceKHR surface = _renderer->getSurface().get(); - _swapChainImageFormat = surfaceFormat.format; - _swapChainExtent = extent; + if(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities) != VK_SUCCESS) + core::error::report(e_kind::fatal_error, "Vulkan : unable to retrieve surface capabilities"); - _imageViews.resize(_swapChainImages.size()); + uint32_t formatCount = 0; + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); - for(size_t i = 0; i < _swapChainImages.size(); i++) - _imageViews[i].init(*this, _swapChainImages[i]); - } + if(formatCount != 0) + { + details.formats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); + } - void SwapChain::initFB() - { - _framebuffers.resize(_imageViews.size()); + uint32_t presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); - for(size_t i = 0; i < _imageViews.size(); i++) - _framebuffers[i].init(*_renderer, _imageViews[i]); - } + if(presentModeCount != 0) + { + details.presentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data()); + } - SwapChain::SwapChainSupportDetails SwapChain::querySwapChainSupport(VkPhysicalDevice device) - { - SwapChain::SwapChainSupportDetails details; - VkSurfaceKHR surface = _renderer->getSurface().get(); + return details; + } - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); + VkPresentModeKHR SwapChain::chooseSwapPresentMode([[maybe_unused]] const std::vector& availablePresentModes) + { + // in the future, you may choose to activate vsync or not + return VK_PRESENT_MODE_IMMEDIATE_KHR; + } - uint32_t formatCount = 0; - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); + VkExtent2D SwapChain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) + { + if(capabilities.currentExtent.width != std::numeric_limits::max()) + return capabilities.currentExtent; - if(formatCount != 0) - { - details.formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); - } - return details; - } + int width, height; + SDL_Vulkan_GetDrawableSize(_renderer->getWindow()->getNativeWindow(), &width, &height); - VkExtent2D SwapChain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) - { - if(capabilities.currentExtent.width != std::numeric_limits::max()) - return capabilities.currentExtent; + VkExtent2D actualExtent = { static_cast(width), static_cast(height) }; - int width, height; - SDL_Vulkan_GetDrawableSize(_renderer->getWindow()->getNativeWindow(), &width, &height); + actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); + actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); - VkExtent2D actualExtent = { static_cast(width), static_cast(height) }; + return actualExtent; + } - actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); - actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); + void SwapChain::recreate() + { + destroy(); + init(_renderer); + } - return actualExtent; - } - - void SwapChain::recreate() - { - destroyFB(); - destroy(); - _renderer->getRenderPass().destroy(); - - init(_renderer); - _renderer->getRenderPass().init(_renderer); - initFB(); - } - - void SwapChain::destroyFB() noexcept - { - vkDeviceWaitIdle(Render_Core::get().getDevice().get()); - - for(size_t i = 0; i < _framebuffers.size(); i++) - _framebuffers[i].destroy(); - } - - void SwapChain::destroy() noexcept - { - vkDeviceWaitIdle(Render_Core::get().getDevice().get()); - - for(size_t i = 0; i < _imageViews.size(); i++) - _imageViews[i].destroy(); - - if(_swapChain != VK_NULL_HANDLE) - vkDestroySwapchainKHR(Render_Core::get().getDevice().get(), _swapChain, nullptr); - _swapChain = VK_NULL_HANDLE; - } + void SwapChain::destroy() noexcept + { + if(_swapChain == VK_NULL_HANDLE) + return; + vkDeviceWaitIdle(Render_Core::get().getDevice().get()); + vkDestroySwapchainKHR(Render_Core::get().getDevice().get(), _swapChain, nullptr); + _swapChain = VK_NULL_HANDLE; + for(Image& img : _images) + { + img.destroyImageView(); + img.destroyCmdPool(); + } + } } diff --git a/src/renderer/swapchain/vk_swapchain.h b/src/renderer/swapchain/vk_swapchain.h index 863219e..315e990 100644 --- a/src/renderer/swapchain/vk_swapchain.h +++ b/src/renderer/swapchain/vk_swapchain.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:23:27 by maldavid #+# #+# */ -/* Updated: 2022/12/18 22:08:36 by maldavid ### ########.fr */ +/* Updated: 2023/11/18 17:15:18 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,15 +15,12 @@ #include #include -#include "vk_imageview.h" -#include "vk_framebuffer.h" +#include namespace mlx { class SwapChain { - friend class FrameBuffer; - friend class ImageView; friend class GraphicPipeline; friend class RenderPass; friend class Renderer; @@ -33,32 +30,36 @@ namespace mlx { VkSurfaceCapabilitiesKHR capabilities; std::vector formats; + std::vector presentModes; }; + public: + SwapChain() = default; + void init(class Renderer* renderer); - void initFB(); - void destroy() noexcept; - void destroyFB() noexcept; - void recreate(); + void destroy() noexcept; - SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); - VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); + SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); + VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); + VkPresentModeKHR chooseSwapPresentMode([[maybe_unused]] const std::vector &availablePresentModes); - inline SwapChainSupportDetails getSupport() noexcept { return _swapChainSupport; } - inline VkSwapchainKHR& operator()() noexcept { return _swapChain; } - inline VkSwapchainKHR& get() noexcept { return _swapChain; } - inline FrameBuffer& getFrameBuffer(int i) { return _framebuffers[i]; } - inline size_t getImagesNumber() const noexcept { return _swapChainImages.size(); } + inline VkSwapchainKHR get() noexcept { return _swapChain; } + inline VkSwapchainKHR operator()() noexcept { return _swapChain; } + inline size_t getImagesNumber() const noexcept { return _images.size(); } + inline Image& getImage(std::size_t i) noexcept { return _images[i]; } + inline SwapChainSupportDetails getSupport() noexcept { return _swapChainSupport; } + inline VkExtent2D getExtent() noexcept { return _extent; } + inline VkFormat getImagesFormat() const noexcept { return _swapChainImageFormat; } + + ~SwapChain() = default; private: - SwapChainSupportDetails _swapChainSupport; - std::vector _swapChainImages; - std::vector _framebuffers; - std::vector _imageViews; - VkSwapchainKHR _swapChain; - VkFormat _swapChainImageFormat; - VkExtent2D _swapChainExtent; + SwapChainSupportDetails _swapChainSupport; + VkSwapchainKHR _swapChain; + std::vector _images; + VkFormat _swapChainImageFormat; + VkExtent2D _extent; class Renderer* _renderer = nullptr; }; } diff --git a/test/main.c b/test/main.c index 110239c..562e762 100644 --- a/test/main.c +++ b/test/main.c @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */ -/* Updated: 2023/11/14 11:14:16 by maldavid ### ########.fr */ +/* Updated: 2023/11/17 09:08:51 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,6 +19,7 @@ typedef struct s_mlx void *mlx; void *win; void *logo; + void *img; } t_mlx; int update(t_mlx *mlx) @@ -28,6 +29,7 @@ int update(t_mlx *mlx) int k; mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo, 100, 100); + mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->img, 220, 20); mlx_string_put(mlx->mlx, mlx->win, 20, 50, 0xFFFFFFFF, "that's a text"); j = 0; k = 0; @@ -102,13 +104,12 @@ int main(void) mlx.logo = mlx_png_file_to_image(mlx.mlx, "42_logo.png", &w, &h); mlx_pixel_put(mlx.mlx, mlx.win, 200, 10, 0xFFFF00FF); mlx_put_image_to_window(mlx.mlx, mlx.win, mlx.logo, 200, 200); - img = create_image(&mlx); + mlx.img = create_image(&mlx); mlx_string_put(mlx.mlx, mlx.win, 20, 20, 0xFFFF2000, \ "that text will disappear"); - mlx_put_image_to_window(mlx.mlx, mlx.win, img, 200, 20); mlx_loop_hook(mlx.mlx, update, &mlx); mlx_loop(mlx.mlx); - mlx_destroy_image(mlx.mlx, img); + mlx_destroy_image(mlx.mlx, mlx.img); mlx_destroy_image(mlx.mlx, mlx.logo); mlx_destroy_window(mlx.mlx, mlx.win); mlx_destroy_display(mlx.mlx);