Allow resizing by default and recreate swapchain on resize (#763)

* Add `stretch to window` support

* Address comment

* Allow window resizing by default and recreate swapchain on resize

---------

Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
Fayaz Shaikh
2026-09-23 09:49:38 -04:00
committed by GitHub
parent f68c77d785
commit 019929587c
2 changed files with 33 additions and 15 deletions
+32 -13
View File
@@ -279,6 +279,7 @@ public:
void Create();
void Recreate(bool surface_lost = false);
[[nodiscard]] bool NeedsResize() const;
[[nodiscard]] Status AcquireNextImage();
[[nodiscard]] bool PrepareSystemOverlay();
void RecordPresentCommands(CommandBuffer& command, VulkanImage& source,
@@ -298,6 +299,8 @@ private:
vk::SwapchainKHR m_handle = nullptr;
vk::Format m_format = vk::Format::eUndefined;
vk::Extent2D m_extent {};
// Drawable pixel size observed when this swapchain was created.
vk::Extent2D m_window_extent {};
std::vector<vk::Image> m_images;
std::vector<vk::ImageView> m_image_views;
std::vector<vk::Semaphore> m_image_acquired;
@@ -357,19 +360,25 @@ void Swapchain::Create() {
EXIT_IF(graphics.device == nullptr);
EXIT_IF(m_window.surface == nullptr);
Common::LockGuard lock(m_window.mutex);
EXIT_IF(graphics.screen_width == 0);
EXIT_IF(graphics.screen_height == 0);
// Capture the size before querying surface capabilities. If the window changes
// during creation, the next presentation will detect the newer size.
{
Common::LockGuard lock(m_window.mutex);
m_window_extent = {graphics.screen_width, graphics.screen_height};
}
EXIT_IF(m_window_extent.width == 0);
EXIT_IF(m_window_extent.height == 0);
m_window.RefreshSurfaceCapabilities();
const auto& surface = m_window.surface_capabilities;
EXIT_NOT_IMPLEMENTED(surface.formats.empty());
m_extent = surface.capabilities.currentExtent;
if (m_extent.width == std::numeric_limits<uint32_t>::max()) {
m_extent.width =
std::clamp(graphics.screen_width, surface.capabilities.minImageExtent.width,
std::clamp(m_window_extent.width, surface.capabilities.minImageExtent.width,
surface.capabilities.maxImageExtent.width);
m_extent.height =
std::clamp(graphics.screen_height, surface.capabilities.minImageExtent.height,
std::clamp(m_window_extent.height, surface.capabilities.minImageExtent.height,
surface.capabilities.maxImageExtent.height);
}
uint32_t image_count = surface.capabilities.minImageCount + 1;
@@ -473,8 +482,8 @@ void Swapchain::Create() {
graphics.device.createSemaphore(&semaphore_info, nullptr, &m_render_complete[i]),
"create swapchain render-complete semaphore");
}
m_image_index = static_cast<uint32_t>(-1);
m_frame_index = 0;
m_image_index = static_cast<uint32_t>(-1);
m_frame_index = 0;
}
Swapchain::~Swapchain() {
@@ -515,11 +524,12 @@ void Swapchain::Destroy() {
graphics.device.destroySwapchainKHR(m_handle, nullptr);
}
m_handle = nullptr;
m_format = vk::Format::eUndefined;
m_extent = {};
m_image_index = static_cast<uint32_t>(-1);
m_frame_index = 0;
m_handle = nullptr;
m_format = vk::Format::eUndefined;
m_extent = {};
m_window_extent = {};
m_image_index = static_cast<uint32_t>(-1);
m_frame_index = 0;
m_images.clear();
m_image_views.clear();
m_image_acquired.clear();
@@ -539,10 +549,15 @@ void Swapchain::Recreate(bool surface_lost) {
m_window.RecreateSurface();
#endif
}
m_window.RefreshSurfaceCapabilities();
Create();
}
bool Swapchain::NeedsResize() const {
Common::LockGuard lock(m_window.mutex);
return m_window_extent.width != m_window.graphic_ctx.screen_width ||
m_window_extent.height != m_window.graphic_ctx.screen_height;
}
Swapchain::Status Swapchain::AcquireNextImage() {
EXIT_IF(m_handle == nullptr || m_frame_index >= m_image_acquired.size());
m_image_index = static_cast<uint32_t>(-1);
@@ -768,6 +783,10 @@ void Presenter::Present(Frame& frame, bool reuse) {
const auto overlay_visual = GetSystemOverlayVisualState();
auto& swapchain = m_impl->swapchain;
// Some window systems keep presenting an old swapchain after a resize.
if (swapchain.NeedsResize()) {
m_impl->RecoverSwapchain(Swapchain::Status::Recreate);
}
for (uint32_t attempt = 0; attempt < 2; attempt++) {
auto status = swapchain.AcquireNextImage();
if (status != Swapchain::Status::Success) {
+1 -2
View File
@@ -783,14 +783,13 @@ static void WindowCreate(WindowContext& context) {
}
SDL_SetWindowPosition(context.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_SetWindowResizable(context.window, false);
HostInputInit(context.window);
InitializeSystemOverlayInput(context.window);
context.UpdateIcon();
}
uint32_t WindowContext::InitialWindowFlags(bool fullscreen) noexcept {
auto flags = static_cast<uint32_t>(SDL_WINDOW_VULKAN);
auto flags = static_cast<uint32_t>(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
if (fullscreen) {
flags |= static_cast<uint32_t>(SDL_WINDOW_FULLSCREEN);
}