Updated swapchain to recreate swapchain with the proper extent required and re-poll the window features on resize.
Swapchain will no longer trigger a resize (internally) if the previous (non-zero) size is equal to the current size
This commit is contained in:
@@ -23,10 +23,12 @@ namespace basalt
|
|||||||
void create_framebuffers(VkRenderPass render_pass);
|
void create_framebuffers(VkRenderPass render_pass);
|
||||||
u32 wait_acquire_reset(bool wait_all=VK_TRUE, u64 timeout=UINT64_MAX, VkFence fence=VK_NULL_HANDLE);
|
u32 wait_acquire_reset(bool wait_all=VK_TRUE, u64 timeout=UINT64_MAX, VkFence fence=VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
basalt::SwapchainSupportDetails details;
|
||||||
basalt::darray<VkSemaphore> semaphores_image_available;
|
basalt::darray<VkSemaphore> semaphores_image_available;
|
||||||
basalt::darray<VkSemaphore> semaphores_render_finished;
|
basalt::darray<VkSemaphore> semaphores_render_finished;
|
||||||
basalt::darray<VkFence> fences_in_flight;
|
basalt::darray<VkFence> fences_in_flight;
|
||||||
basalt::SwapchainSupportDetails details;
|
basalt::darray<VkSurfaceFormatKHR> allowed_formats;
|
||||||
|
basalt::darray<VkPresentModeKHR> allowed_present_modes;
|
||||||
basalt::darray<VkImage> swapchain_images;
|
basalt::darray<VkImage> swapchain_images;
|
||||||
basalt::darray<VkImageView> swapchain_image_views;
|
basalt::darray<VkImageView> swapchain_image_views;
|
||||||
basalt::darray<VkFramebuffer> framebuffers;
|
basalt::darray<VkFramebuffer> framebuffers;
|
||||||
@@ -34,12 +36,13 @@ namespace basalt
|
|||||||
basalt::Window* window = nullptr;
|
basalt::Window* window = nullptr;
|
||||||
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
|
VkSwapchainKHR swapchain = VK_NULL_HANDLE;
|
||||||
VkExtent2D swapchain_extent;
|
VkExtent2D swapchain_extent;
|
||||||
|
VkExtent2D prev_extent;
|
||||||
u32 image_count = -1;
|
u32 image_count = -1;
|
||||||
u32 max_frames_in_flight = 2;
|
u32 max_frames_in_flight = 2;
|
||||||
u32 current_frame = 0;
|
u32 current_frame = 0;
|
||||||
bool framebuffers_created = false;
|
bool framebuffers_created = false;
|
||||||
private:
|
private:
|
||||||
void create (const std::initializer_list<VkSurfaceFormatKHR>& allowed_formats,
|
void create (const basalt::darray<VkSurfaceFormatKHR>& allowed_formats,
|
||||||
const std::initializer_list<VkPresentModeKHR> allowed_present_modes, VkSwapchainKHR prev_swapchain=VK_NULL_HANDLE);
|
const basalt::darray<VkPresentModeKHR>& allowed_present_modes, VkSwapchainKHR prev_swapchain=VK_NULL_HANDLE);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,15 @@ basalt::Swapchain::Swapchain(basalt::Device& device, basalt::Window& window,
|
|||||||
framebuffers(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
framebuffers(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||||
semaphores_image_available(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
semaphores_image_available(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||||
semaphores_render_finished(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
semaphores_render_finished(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||||
fences_in_flight(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY)
|
fences_in_flight(MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||||
|
allowed_formats(allowed_formats, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY),
|
||||||
|
allowed_present_modes(allowed_present_modes, MEMORY_TAG_CLASS_ARRAY | MEMORY_TAG_ZONE_ENGINE | MEMORY_TAG_ALIGN_ANY)
|
||||||
{
|
{
|
||||||
this->framebuffers_created = false;
|
this->framebuffers_created = false;
|
||||||
this->create(allowed_formats, allowed_present_modes, VK_NULL_HANDLE);
|
this->details.requery(window, device, this->allowed_formats, this->allowed_present_modes);
|
||||||
|
this->swapchain_extent = details.get_framebuffer_extent(window);
|
||||||
|
this->prev_extent = { .width = 0, .height = 0 };
|
||||||
|
this->create(this->allowed_formats, this->allowed_present_modes, VK_NULL_HANDLE);
|
||||||
|
|
||||||
VkResult err = VK_SUCCESS;
|
VkResult err = VK_SUCCESS;
|
||||||
VkSemaphoreCreateInfo semaphore_ci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
VkSemaphoreCreateInfo semaphore_ci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
||||||
@@ -52,23 +57,33 @@ basalt::Swapchain::~Swapchain()
|
|||||||
|
|
||||||
void basalt::Swapchain::recreate(VkRenderPass new_renderpass)
|
void basalt::Swapchain::recreate(VkRenderPass new_renderpass)
|
||||||
{
|
{
|
||||||
swapchain_extent = details.get_framebuffer_extent(*window);
|
swapchain_extent = details.get_framebuffer_extent(*window, false);
|
||||||
if (swapchain_extent.width == 0 || swapchain_extent.height == 0)
|
if (swapchain_extent.width == 0 || swapchain_extent.height == 0)
|
||||||
return;
|
return;
|
||||||
|
details.requery(*window, *device, allowed_formats, allowed_present_modes);
|
||||||
|
swapchain_extent = details.get_framebuffer_extent(*window, true);
|
||||||
|
if (prev_extent.width == swapchain_extent.width && prev_extent.height == swapchain_extent.height && framebuffers.m_nelements > 0)
|
||||||
|
{
|
||||||
|
this->framebuffers_created = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev_extent = swapchain_extent;
|
||||||
vkDeviceWaitIdle(device->logical);
|
vkDeviceWaitIdle(device->logical);
|
||||||
|
|
||||||
|
BTRACE("Recreating swapchain %p\n");
|
||||||
for (VkImageView& view : this->swapchain_image_views)
|
for (VkImageView& view : this->swapchain_image_views)
|
||||||
vkDestroyImageView(*this->device, view, this->device->ctx->vk_alloc);
|
vkDestroyImageView(*this->device, view, this->device->ctx->vk_alloc);
|
||||||
vkDestroySwapchainKHR(*device, this->swapchain, device->ctx->vk_alloc);
|
vkDestroySwapchainKHR(*device, this->swapchain, device->ctx->vk_alloc);
|
||||||
|
|
||||||
// TODO: store the prefered format/present list and use them
|
this->create(allowed_formats, allowed_present_modes, VK_NULL_HANDLE);
|
||||||
this->create({ details.cached_format }, { details.cached_present_mode }, VK_NULL_HANDLE);
|
|
||||||
if (new_renderpass != VK_NULL_HANDLE)
|
if (new_renderpass != VK_NULL_HANDLE)
|
||||||
this->create_framebuffers(new_renderpass);
|
this->create_framebuffers(new_renderpass);
|
||||||
}
|
}
|
||||||
|
|
||||||
void basalt::Swapchain::create_framebuffers(VkRenderPass render_pass)
|
void basalt::Swapchain::create_framebuffers(VkRenderPass render_pass)
|
||||||
{
|
{
|
||||||
|
if (swapchain_extent.width == 0 || swapchain_extent.height == 0)
|
||||||
|
return;
|
||||||
if (framebuffers.m_nelements != 0 || framebuffers_created)
|
if (framebuffers.m_nelements != 0 || framebuffers_created)
|
||||||
{
|
{
|
||||||
vkDeviceWaitIdle(*device);
|
vkDeviceWaitIdle(*device);
|
||||||
@@ -92,6 +107,7 @@ void basalt::Swapchain::create_framebuffers(VkRenderPass render_pass)
|
|||||||
}
|
}
|
||||||
framebuffers.m_nelements = swapchain_image_views.m_nelements;
|
framebuffers.m_nelements = swapchain_image_views.m_nelements;
|
||||||
framebuffers_created = true;
|
framebuffers_created = true;
|
||||||
|
BTRACE("Created %u framebuffers of size (%u, %u), for swapchain %p and renderpass %p\n", max_frames_in_flight, swapchain_extent.width, swapchain_extent.height, this, render_pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 basalt::Swapchain::wait_acquire_reset(bool wait_all, u64 timeout, VkFence fence)
|
u32 basalt::Swapchain::wait_acquire_reset(bool wait_all, u64 timeout, VkFence fence)
|
||||||
@@ -113,8 +129,8 @@ u32 basalt::Swapchain::wait_acquire_reset(bool wait_all, u64 timeout, VkFence fe
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void basalt::Swapchain::create(const std::initializer_list<VkSurfaceFormatKHR>& allowed_formats,
|
void basalt::Swapchain::create(const basalt::darray<VkSurfaceFormatKHR>& allowed_formats,
|
||||||
const std::initializer_list<VkPresentModeKHR> allowed_present_modes, VkSwapchainKHR prev_swapchain)
|
const basalt::darray<VkPresentModeKHR>& allowed_present_modes, VkSwapchainKHR prev_swapchain)
|
||||||
{
|
{
|
||||||
this->image_count = details.surface_capabilities.minImageCount + 1;
|
this->image_count = details.surface_capabilities.minImageCount + 1;
|
||||||
BCLAMP(this->image_count, details.surface_capabilities.minImageCount, details.surface_capabilities.maxImageCount);
|
BCLAMP(this->image_count, details.surface_capabilities.minImageCount, details.surface_capabilities.maxImageCount);
|
||||||
@@ -150,7 +166,6 @@ void basalt::Swapchain::create(const std::initializer_list<VkSurfaceFormatKHR>&
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkResult err = VK_SUCCESS;
|
VkResult err = VK_SUCCESS;
|
||||||
this->swapchain_extent = ci.imageExtent;
|
|
||||||
VK_ASSERT(vkCreateSwapchainKHR(device->logical, &ci, device->ctx->vk_alloc, &this->swapchain), "Failed to create swapchain\n\tAt %s:%d\n\tError %s\n");
|
VK_ASSERT(vkCreateSwapchainKHR(device->logical, &ci, device->ctx->vk_alloc, &this->swapchain), "Failed to create swapchain\n\tAt %s:%d\n\tError %s\n");
|
||||||
|
|
||||||
u32 n_images = 0;
|
u32 n_images = 0;
|
||||||
@@ -179,4 +194,5 @@ void basalt::Swapchain::create(const std::initializer_list<VkSurfaceFormatKHR>&
|
|||||||
VK_ASSERT(vkCreateImageView(device->logical, &view_ci, device->ctx->vk_alloc, &swapchain_image_views[i]), "Failed to create image view\n\tAt %s:%d\n\tError %s\n\tImage index: %u\n", i);
|
VK_ASSERT(vkCreateImageView(device->logical, &view_ci, device->ctx->vk_alloc, &swapchain_image_views[i]), "Failed to create image view\n\tAt %s:%d\n\tError %s\n\tImage index: %u\n", i);
|
||||||
}
|
}
|
||||||
swapchain_image_views.m_nelements = n_images;
|
swapchain_image_views.m_nelements = n_images;
|
||||||
|
BTRACE("Created swapchain %p with %u images and extent %u x %u\n", this, max_frames_in_flight, swapchain_extent.width, swapchain_extent.height);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user