vk: Allow swapchain create to fail with an error

This commit is contained in:
kd-11 2017-10-29 12:57:00 +03:00
parent 7e6d6b45d4
commit f8f5f9f418
2 changed files with 41 additions and 14 deletions

View File

@ -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));

View File

@ -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<vk::physical_device&>(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()