cleaning renderpass, framebuffers and swapchain code, setting all vulkan resources to NULL after destroy

This commit is contained in:
Kbz-8
2023-11-18 17:25:30 +01:00
parent c583f1abc8
commit f6201014aa
23 changed files with 435 additions and 299 deletions

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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
{
if(_fence != VK_NULL_HANDLE)
vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr);
_fence = VK_NULL_HANDLE;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<VkAccessFlagBits>(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)

View File

@@ -6,12 +6,12 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <volk.h>
#include <cstddef>
@@ -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;
};

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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();
@@ -60,10 +62,10 @@ namespace mlx
{
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<float>(fb.getWidth());
viewport.height = static_cast<float>(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();

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <renderer/pipeline/pipeline.h>
#include <renderer/command/cmd_manager.h>
#include <renderer/swapchain/vk_swapchain.h>
#include <renderer/swapchain/vk_render_pass.h>
#include <renderer/renderpass/vk_render_pass.h>
#include <renderer/renderpass/vk_framebuffer.h>
#include <renderer/descriptors/vk_descriptor_set.h>
#include <renderer/descriptors/vk_descriptor_pool.h>
#include <renderer/descriptors/vk_descriptor_set_layout.h>
@@ -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<Semaphore, MAX_FRAMES_IN_FLIGHT> _semaphores;
std::vector<FrameBuffer> _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;
};

View File

@@ -6,27 +6,31 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <volk.h>
#include <renderer/core/render_core.h>
#include <renderer/renderer.h>
#include <renderer/images/vk_image.h>
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;
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
@@ -20,14 +20,18 @@ namespace mlx
class FrameBuffer
{
public:
void init(class Renderer& renderer, class ImageView& image);
void init(class RenderPass& renderpass, class Image& image);
void destroy() noexcept;
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;
uint32_t _width = 0;
uint32_t _height = 0;
};
}

View File

@@ -6,24 +6,23 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <renderer/core/render_core.h>
#include <renderer/renderer.h>
#include <renderer/renderpass/vk_framebuffer.h>
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;
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
};
}

View File

@@ -1,47 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_imageview.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <renderer/core/render_core.h>
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);
}
}

View File

@@ -1,34 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* vk_imageview.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <volk.h>
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__

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
@@ -20,32 +20,36 @@ namespace mlx
{
void SwapChain::init(Renderer* renderer)
{
_renderer = renderer;
VkDevice device = Render_Core::get().getDevice().get();
_renderer = renderer;
_swapChainSupport = querySwapChainSupport(Render_Core::get().getDevice().getPhysicalDevice());
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);
VkPresentModeKHR presentMode = chooseSwapPresentMode(_swapChainSupport.presentModes);
_extent = chooseSwapExtent(_swapChainSupport.capabilities);
uint32_t imageCount = _swapChainSupport.capabilities.minImageCount + 1;
if(_swapChainSupport.capabilities.maxImageCount > 0 && imageCount > _swapChainSupport.capabilities.maxImageCount)
imageCount = _swapChainSupport.capabilities.maxImageCount;
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() };
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;
@@ -55,40 +59,26 @@ namespace mlx
else
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;
createInfo.oldSwapchain = VK_NULL_HANDLE;
VkDevice device = Render_Core::get().getDevice().get();
if(vkCreateSwapchainKHR(device, &createInfo, nullptr, &_swapChain) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create swapchain");
core::error::report(e_kind::fatal_error, "Vulkan : failed to create the swapchain");
std::vector<VkImage> tmp;
vkGetSwapchainImagesKHR(device, _swapChain, &imageCount, nullptr);
_images.resize(imageCount);
tmp.resize(imageCount);
vkGetSwapchainImagesKHR(device, _swapChain, &imageCount, tmp.data());
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);
}
_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());
_swapChainImageFormat = surfaceFormat.format;
_swapChainExtent = extent;
_imageViews.resize(_swapChainImages.size());
for(size_t i = 0; i < _swapChainImages.size(); i++)
_imageViews[i].init(*this, _swapChainImages[i]);
}
void SwapChain::initFB()
{
_framebuffers.resize(_imageViews.size());
for(size_t i = 0; i < _imageViews.size(); i++)
_framebuffers[i].init(*_renderer, _imageViews[i]);
}
SwapChain::SwapChainSupportDetails SwapChain::querySwapChainSupport(VkPhysicalDevice device)
@@ -96,7 +86,8 @@ namespace mlx
SwapChain::SwapChainSupportDetails details;
VkSurfaceKHR surface = _renderer->getSurface().get();
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
if(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : unable to retrieve surface capabilities");
uint32_t formatCount = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
@@ -106,9 +97,25 @@ namespace mlx
details.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
}
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
if(presentModeCount != 0)
{
details.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
}
return details;
}
VkPresentModeKHR SwapChain::chooseSwapPresentMode([[maybe_unused]] const std::vector<VkPresentModeKHR>& availablePresentModes)
{
// in the future, you may choose to activate vsync or not
return VK_PRESENT_MODE_IMMEDIATE_KHR;
}
VkExtent2D SwapChain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities)
{
if(capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
@@ -127,32 +134,21 @@ namespace mlx
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
{
if(_swapChain == VK_NULL_HANDLE)
return;
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;
for(Image& img : _images)
{
img.destroyImageView();
img.destroyCmdPool();
}
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <vector>
#include <volk.h>
#include "vk_imageview.h"
#include "vk_framebuffer.h"
#include <renderer/images/vk_image.h>
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<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
void init(class Renderer* renderer);
void initFB();
void destroy() noexcept;
void destroyFB() noexcept;
public:
SwapChain() = default;
void init(class Renderer* renderer);
void recreate();
void destroy() noexcept;
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
VkPresentModeKHR chooseSwapPresentMode([[maybe_unused]] const std::vector<VkPresentModeKHR> &availablePresentModes);
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 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 VkExtent2D getExtent() noexcept { return _extent; }
inline VkFormat getImagesFormat() const noexcept { return _swapChainImageFormat; }
~SwapChain() = default;
private:
SwapChainSupportDetails _swapChainSupport;
std::vector<VkImage> _swapChainImages;
std::vector<FrameBuffer> _framebuffers;
std::vector<ImageView> _imageViews;
VkSwapchainKHR _swapChain;
std::vector<Image> _images;
VkFormat _swapChainImageFormat;
VkExtent2D _swapChainExtent;
VkExtent2D _extent;
class Renderer* _renderer = nullptr;
};
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);