diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index e5173bdbfa..a7c88c39e9 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -551,7 +551,8 @@ VKGSRender::VKGSRender() : GSRender() m_client_width = m_frame->client_width(); m_client_height = m_frame->client_height(); - m_swap_chain->init_swapchain(m_client_width, m_client_height); + if (!m_swap_chain->init_swapchain(m_client_width, m_client_height)) + present_surface_dirty_flag = true; //create command buffer... m_command_buffer_pool.create((*m_device)); @@ -2405,10 +2406,13 @@ void VKGSRender::prepare_rtts() void VKGSRender::reinitialize_swapchain() { + const auto new_width = m_frame->client_width(); + const auto new_height = m_frame->client_height(); + //Reject requests to acquire new swapchain if the window is minimized //The NVIDIA driver will spam VK_ERROR_OUT_OF_DATE_KHR if you try to acquire an image from the swapchain and the window is minimized //However, any attempt to actually renew the swapchain will crash the driver with VK_ERROR_DEVICE_LOST while the window is in this state - if (m_frame->client_width() == 0 || m_frame->client_height() == 0) + if (new_width == 0 || new_height == 0) return; /** @@ -2421,13 +2425,6 @@ void VKGSRender::reinitialize_swapchain() m_current_command_buffer->pending = true; m_current_command_buffer->reset(); - //Will have to block until rendering is completed - VkFence resize_fence = VK_NULL_HANDLE; - VkFenceCreateInfo infos = {}; - infos.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - - vkCreateFence((*m_device), &infos, nullptr, &resize_fence); - for (auto &ctx : frame_context_storage) { if (ctx.present_image == UINT32_MAX) @@ -2446,9 +2443,16 @@ void VKGSRender::reinitialize_swapchain() m_framebuffers_to_clean.clear(); //Rebuild swapchain. Old swapchain destruction is handled by the init_swapchain call - m_client_width = m_frame->client_width(); - m_client_height = m_frame->client_height(); - m_swap_chain->init_swapchain(m_client_width, m_client_height); + if (!m_swap_chain->init_swapchain(new_width, new_height)) + { + LOG_WARNING(RSX, "Swapchain initialization failed. Request ignored [%dx%d]", new_width, new_height); + present_surface_dirty_flag = false; + open_command_buffer(); + return; + } + + m_client_width = new_width; + m_client_height = new_height; //Prepare new swapchain images for use open_command_buffer(); @@ -2467,6 +2471,13 @@ void VKGSRender::reinitialize_swapchain() vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT)); } + //Will have to block until rendering is completed + VkFence resize_fence = VK_NULL_HANDLE; + VkFenceCreateInfo infos = {}; + infos.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + + vkCreateFence((*m_device), &infos, nullptr, &resize_fence); + //Flush the command buffer close_and_submit_command_buffer({}, resize_fence); CHECK_RESULT(vkWaitForFences((*m_device), 1, &resize_fence, VK_TRUE, UINT64_MAX)); diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index ecf1c3d95e..3d66d0c099 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -809,7 +809,7 @@ namespace vk } } - void init_swapchain(u32 width, u32 height) + bool init_swapchain(u32 width, u32 height) { VkSwapchainKHR old_swapchain = m_vk_swapchain; vk::physical_device& gpu = const_cast(dev.gpu()); @@ -817,8 +817,16 @@ namespace vk VkSurfaceCapabilitiesKHR surface_descriptors = {}; CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, m_surface, &surface_descriptors)); - VkExtent2D swapchainExtent; + if (surface_descriptors.maxImageExtent.width < width || + surface_descriptors.maxImageExtent.height < height) + { + LOG_ERROR(RSX, "Swapchain: Swapchain creation failed because dimensions cannot fit. Max = %d, %d, Requested = %d, %d", + surface_descriptors.maxImageExtent.width, surface_descriptors.maxImageExtent.height, width, height); + return false; + } + + VkExtent2D swapchainExtent; if (surface_descriptors.currentExtent.width == (uint32_t)-1) { swapchainExtent.width = width; @@ -826,6 +834,12 @@ namespace vk } else { + if (surface_descriptors.currentExtent.width == 0 || surface_descriptors.currentExtent.height == 0) + { + LOG_WARNING(RSX, "Swapchain: Current surface extent is a null region. Is the window minimized?"); + return false; + } + swapchainExtent = surface_descriptors.currentExtent; width = surface_descriptors.currentExtent.width; height = surface_descriptors.currentExtent.height; @@ -932,6 +946,8 @@ namespace vk { m_swap_images[i].create(dev, swap_images[i], m_surface_format); } + + return true; } u32 get_swap_image_count()