mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +00:00
VulkanDevice: Release swap chain images on resize
This commit is contained in:
parent
6892c3d095
commit
1797050f97
|
@ -269,6 +269,8 @@ bool VulkanDevice::SelectInstanceExtensions(ExtensionList* extension_list, const
|
||||||
// Needed for exclusive fullscreen control.
|
// Needed for exclusive fullscreen control.
|
||||||
SupportsExtension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, false);
|
SupportsExtension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, false);
|
||||||
|
|
||||||
|
oe->vk_ext_swapchain_maintenance1 =
|
||||||
|
(wi.type != WindowInfo::Type::Surfaceless && SupportsExtension(VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME, false));
|
||||||
oe->vk_khr_get_physical_device_properties2 =
|
oe->vk_khr_get_physical_device_properties2 =
|
||||||
SupportsExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
|
SupportsExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
|
||||||
|
|
||||||
|
@ -409,6 +411,9 @@ bool VulkanDevice::SelectDeviceExtensions(ExtensionList* extension_list, bool en
|
||||||
|
|
||||||
m_optional_extensions.vk_ext_external_memory_host =
|
m_optional_extensions.vk_ext_external_memory_host =
|
||||||
SupportsExtension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, false);
|
SupportsExtension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, false);
|
||||||
|
m_optional_extensions.vk_ext_swapchain_maintenance1 =
|
||||||
|
m_optional_extensions.vk_ext_swapchain_maintenance1 &&
|
||||||
|
SupportsExtension(VK_EXT_SWAPCHAIN_MAINTENANCE_1_EXTENSION_NAME, false);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
m_optional_extensions.vk_ext_full_screen_exclusive =
|
m_optional_extensions.vk_ext_full_screen_exclusive =
|
||||||
|
@ -581,9 +586,13 @@ bool VulkanDevice::CreateDevice(VkSurfaceKHR surface, bool enable_validation_lay
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, nullptr, VK_TRUE};
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, nullptr, VK_TRUE};
|
||||||
VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR dynamic_rendering_local_read_feature = {
|
VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR dynamic_rendering_local_read_feature = {
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR, nullptr, VK_TRUE};
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR, nullptr, VK_TRUE};
|
||||||
|
VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT swapchain_maintenance1_feature = {
|
||||||
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT, nullptr, VK_TRUE};
|
||||||
|
|
||||||
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
|
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
|
||||||
Vulkan::AddPointerToChain(&device_info, &rasterization_order_access_feature);
|
Vulkan::AddPointerToChain(&device_info, &rasterization_order_access_feature);
|
||||||
|
if (m_optional_extensions.vk_ext_swapchain_maintenance1)
|
||||||
|
Vulkan::AddPointerToChain(&device_info, &swapchain_maintenance1_feature);
|
||||||
if (m_optional_extensions.vk_khr_dynamic_rendering)
|
if (m_optional_extensions.vk_khr_dynamic_rendering)
|
||||||
{
|
{
|
||||||
Vulkan::AddPointerToChain(&device_info, &dynamic_rendering_feature);
|
Vulkan::AddPointerToChain(&device_info, &dynamic_rendering_feature);
|
||||||
|
@ -631,10 +640,14 @@ void VulkanDevice::ProcessDeviceExtensions()
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, nullptr, VK_FALSE};
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, nullptr, VK_FALSE};
|
||||||
VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR dynamic_rendering_local_read_feature = {
|
VkPhysicalDeviceDynamicRenderingLocalReadFeaturesKHR dynamic_rendering_local_read_feature = {
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR, nullptr, VK_FALSE};
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES_KHR, nullptr, VK_FALSE};
|
||||||
|
VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT swapchain_maintenance1_feature = {
|
||||||
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT, nullptr, VK_FALSE};
|
||||||
|
|
||||||
// add in optional feature structs
|
// add in optional feature structs
|
||||||
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
|
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
|
||||||
Vulkan::AddPointerToChain(&features2, &rasterization_order_access_feature);
|
Vulkan::AddPointerToChain(&features2, &rasterization_order_access_feature);
|
||||||
|
if (m_optional_extensions.vk_ext_swapchain_maintenance1)
|
||||||
|
Vulkan::AddPointerToChain(&features2, &swapchain_maintenance1_feature);
|
||||||
if (m_optional_extensions.vk_khr_dynamic_rendering)
|
if (m_optional_extensions.vk_khr_dynamic_rendering)
|
||||||
{
|
{
|
||||||
Vulkan::AddPointerToChain(&features2, &dynamic_rendering_feature);
|
Vulkan::AddPointerToChain(&features2, &dynamic_rendering_feature);
|
||||||
|
@ -669,6 +682,8 @@ void VulkanDevice::ProcessDeviceExtensions()
|
||||||
// confirm we actually support it
|
// confirm we actually support it
|
||||||
m_optional_extensions.vk_ext_rasterization_order_attachment_access &=
|
m_optional_extensions.vk_ext_rasterization_order_attachment_access &=
|
||||||
(rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
|
(rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
|
||||||
|
m_optional_extensions.vk_ext_swapchain_maintenance1 &=
|
||||||
|
(swapchain_maintenance1_feature.swapchainMaintenance1 == VK_TRUE);
|
||||||
m_optional_extensions.vk_khr_dynamic_rendering &= (dynamic_rendering_feature.dynamicRendering == VK_TRUE);
|
m_optional_extensions.vk_khr_dynamic_rendering &= (dynamic_rendering_feature.dynamicRendering == VK_TRUE);
|
||||||
m_optional_extensions.vk_khr_dynamic_rendering_local_read &=
|
m_optional_extensions.vk_khr_dynamic_rendering_local_read &=
|
||||||
(dynamic_rendering_local_read_feature.dynamicRenderingLocalRead == VK_TRUE);
|
(dynamic_rendering_local_read_feature.dynamicRenderingLocalRead == VK_TRUE);
|
||||||
|
@ -700,9 +715,13 @@ void VulkanDevice::ProcessDeviceExtensions()
|
||||||
m_optional_extensions.vk_ext_external_memory_host &=
|
m_optional_extensions.vk_ext_external_memory_host &=
|
||||||
(external_memory_host_properties.minImportedHostPointerAlignment == HOST_PAGE_SIZE);
|
(external_memory_host_properties.minImportedHostPointerAlignment == HOST_PAGE_SIZE);
|
||||||
|
|
||||||
|
INFO_LOG("VK_EXT_external_memory_host is {}",
|
||||||
|
m_optional_extensions.vk_ext_external_memory_host ? "supported" : "NOT supported");
|
||||||
INFO_LOG("VK_EXT_memory_budget is {}", m_optional_extensions.vk_ext_memory_budget ? "supported" : "NOT supported");
|
INFO_LOG("VK_EXT_memory_budget is {}", m_optional_extensions.vk_ext_memory_budget ? "supported" : "NOT supported");
|
||||||
INFO_LOG("VK_EXT_rasterization_order_attachment_access is {}",
|
INFO_LOG("VK_EXT_rasterization_order_attachment_access is {}",
|
||||||
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
|
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
|
||||||
|
INFO_LOG("VK_EXT_swapchain_maintenance1 is {}",
|
||||||
|
m_optional_extensions.vk_ext_swapchain_maintenance1 ? "supported" : "NOT supported");
|
||||||
INFO_LOG("VK_KHR_get_memory_requirements2 is {}",
|
INFO_LOG("VK_KHR_get_memory_requirements2 is {}",
|
||||||
m_optional_extensions.vk_khr_get_memory_requirements2 ? "supported" : "NOT supported");
|
m_optional_extensions.vk_khr_get_memory_requirements2 ? "supported" : "NOT supported");
|
||||||
INFO_LOG("VK_KHR_bind_memory2 is {}", m_optional_extensions.vk_khr_bind_memory2 ? "supported" : "NOT supported");
|
INFO_LOG("VK_KHR_bind_memory2 is {}", m_optional_extensions.vk_khr_bind_memory2 ? "supported" : "NOT supported");
|
||||||
|
@ -716,8 +735,6 @@ void VulkanDevice::ProcessDeviceExtensions()
|
||||||
m_optional_extensions.vk_khr_dynamic_rendering_local_read ? "supported" : "NOT supported");
|
m_optional_extensions.vk_khr_dynamic_rendering_local_read ? "supported" : "NOT supported");
|
||||||
INFO_LOG("VK_KHR_push_descriptor is {}",
|
INFO_LOG("VK_KHR_push_descriptor is {}",
|
||||||
m_optional_extensions.vk_khr_push_descriptor ? "supported" : "NOT supported");
|
m_optional_extensions.vk_khr_push_descriptor ? "supported" : "NOT supported");
|
||||||
INFO_LOG("VK_EXT_external_memory_host is {}",
|
|
||||||
m_optional_extensions.vk_ext_external_memory_host ? "supported" : "NOT supported");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanDevice::CreateAllocator()
|
bool VulkanDevice::CreateAllocator()
|
||||||
|
@ -1350,16 +1367,17 @@ void VulkanDevice::DoPresent(VulkanSwapChain* present_swap_chain)
|
||||||
present_swap_chain->GetCurrentImageIndexPtr(),
|
present_swap_chain->GetCurrentImageIndexPtr(),
|
||||||
nullptr};
|
nullptr};
|
||||||
|
|
||||||
present_swap_chain->ReleaseCurrentImage();
|
present_swap_chain->ResetImageAcquireResult();
|
||||||
|
|
||||||
const VkResult res = vkQueuePresentKHR(m_present_queue, &present_info);
|
const VkResult res = vkQueuePresentKHR(m_present_queue, &present_info);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR)
|
||||||
{
|
{
|
||||||
// VK_ERROR_OUT_OF_DATE_KHR is not fatal, just means we need to recreate our swap chain.
|
// VK_ERROR_OUT_OF_DATE_KHR is not fatal, just means we need to recreate our swap chain.
|
||||||
if (res != VK_ERROR_OUT_OF_DATE_KHR && res != VK_SUBOPTIMAL_KHR)
|
if (res == VK_ERROR_OUT_OF_DATE_KHR)
|
||||||
|
ResizeWindow(0, 0, m_window_info.surface_scale);
|
||||||
|
else
|
||||||
LOG_VULKAN_ERROR(res, "vkQueuePresentKHR failed: ");
|
LOG_VULKAN_ERROR(res, "vkQueuePresentKHR failed: ");
|
||||||
|
|
||||||
m_last_present_failed.store(true, std::memory_order_release);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1521,11 +1539,6 @@ void VulkanDevice::SubmitCommandBufferAndRestartRenderPass(const char* reason)
|
||||||
BeginRenderPass();
|
BeginRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanDevice::CheckLastPresentFail()
|
|
||||||
{
|
|
||||||
return m_last_present_failed.exchange(false, std::memory_order_acq_rel);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VulkanDevice::CheckLastSubmitFail()
|
bool VulkanDevice::CheckLastSubmitFail()
|
||||||
{
|
{
|
||||||
return m_last_submit_failed.load(std::memory_order_acquire);
|
return m_last_submit_failed.load(std::memory_order_acquire);
|
||||||
|
|
|
@ -42,9 +42,11 @@ public:
|
||||||
|
|
||||||
struct OptionalExtensions
|
struct OptionalExtensions
|
||||||
{
|
{
|
||||||
|
bool vk_ext_external_memory_host : 1;
|
||||||
|
bool vk_ext_full_screen_exclusive : 1;
|
||||||
bool vk_ext_memory_budget : 1;
|
bool vk_ext_memory_budget : 1;
|
||||||
bool vk_ext_rasterization_order_attachment_access : 1;
|
bool vk_ext_rasterization_order_attachment_access : 1;
|
||||||
bool vk_ext_full_screen_exclusive : 1;
|
bool vk_ext_swapchain_maintenance1 : 1;
|
||||||
bool vk_khr_get_memory_requirements2 : 1;
|
bool vk_khr_get_memory_requirements2 : 1;
|
||||||
bool vk_khr_bind_memory2 : 1;
|
bool vk_khr_bind_memory2 : 1;
|
||||||
bool vk_khr_get_physical_device_properties2 : 1;
|
bool vk_khr_get_physical_device_properties2 : 1;
|
||||||
|
@ -54,7 +56,6 @@ public:
|
||||||
bool vk_khr_dynamic_rendering_local_read : 1;
|
bool vk_khr_dynamic_rendering_local_read : 1;
|
||||||
bool vk_khr_push_descriptor : 1;
|
bool vk_khr_push_descriptor : 1;
|
||||||
bool vk_khr_shader_non_semantic_info : 1;
|
bool vk_khr_shader_non_semantic_info : 1;
|
||||||
bool vk_ext_external_memory_host : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static GPUTexture::Format GetFormatForVkFormat(VkFormat format);
|
static GPUTexture::Format GetFormatForVkFormat(VkFormat format);
|
||||||
|
@ -318,9 +319,6 @@ private:
|
||||||
void EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present, bool submit_on_thread);
|
void EndAndSubmitCommandBuffer(VulkanSwapChain* present_swap_chain, bool explicit_present, bool submit_on_thread);
|
||||||
void MoveToNextCommandBuffer();
|
void MoveToNextCommandBuffer();
|
||||||
void WaitForPresentComplete();
|
void WaitForPresentComplete();
|
||||||
|
|
||||||
// Was the last present submitted to the queue a failure? If so, we must recreate our swapchain.
|
|
||||||
bool CheckLastPresentFail();
|
|
||||||
bool CheckLastSubmitFail();
|
bool CheckLastSubmitFail();
|
||||||
|
|
||||||
using ExtensionList = std::vector<const char*>;
|
using ExtensionList = std::vector<const char*>;
|
||||||
|
@ -415,7 +413,6 @@ private:
|
||||||
u32 m_current_frame = 0;
|
u32 m_current_frame = 0;
|
||||||
|
|
||||||
std::atomic_bool m_last_submit_failed{false};
|
std::atomic_bool m_last_submit_failed{false};
|
||||||
std::atomic_bool m_last_present_failed{false};
|
|
||||||
std::atomic_bool m_present_done{true};
|
std::atomic_bool m_present_done{true};
|
||||||
std::mutex m_present_mutex;
|
std::mutex m_present_mutex;
|
||||||
std::condition_variable m_present_queued_cv;
|
std::condition_variable m_present_queued_cv;
|
||||||
|
|
|
@ -251,5 +251,7 @@ VULKAN_DEVICE_ENTRY_POINT(vkCmdPushDescriptorSetKHR, false)
|
||||||
// VK_EXT_external_memory_host
|
// VK_EXT_external_memory_host
|
||||||
VULKAN_DEVICE_ENTRY_POINT(vkGetMemoryHostPointerPropertiesEXT, false)
|
VULKAN_DEVICE_ENTRY_POINT(vkGetMemoryHostPointerPropertiesEXT, false)
|
||||||
|
|
||||||
|
// VK_EXT_swapchain_maintenance1
|
||||||
|
VULKAN_DEVICE_ENTRY_POINT(vkReleaseSwapchainImagesEXT, false)
|
||||||
|
|
||||||
#endif // VULKAN_DEVICE_ENTRY_POINT
|
#endif // VULKAN_DEVICE_ENTRY_POINT
|
||||||
|
|
|
@ -623,12 +623,35 @@ VkResult VulkanSwapChain::AcquireNextImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanSwapChain::ReleaseCurrentImage()
|
void VulkanSwapChain::ReleaseCurrentImage()
|
||||||
|
{
|
||||||
|
if (!m_image_acquire_result.has_value())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((m_image_acquire_result.value() == VK_SUCCESS || m_image_acquire_result.value() == VK_SUBOPTIMAL_KHR) &&
|
||||||
|
VulkanDevice::GetInstance().GetOptionalExtensions().vk_ext_swapchain_maintenance1)
|
||||||
|
{
|
||||||
|
VulkanDevice::GetInstance().WaitForGPUIdle();
|
||||||
|
|
||||||
|
const VkReleaseSwapchainImagesInfoEXT info = {.sType = VK_STRUCTURE_TYPE_RELEASE_SWAPCHAIN_IMAGES_INFO_EXT,
|
||||||
|
.swapchain = m_swap_chain,
|
||||||
|
.imageIndexCount = 1,
|
||||||
|
.pImageIndices = &m_current_image};
|
||||||
|
VkResult res = vkReleaseSwapchainImagesEXT(VulkanDevice::GetInstance().GetVulkanDevice(), &info);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
LOG_VULKAN_ERROR(res, "vkReleaseSwapchainImagesEXT() failed: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_image_acquire_result.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanSwapChain::ResetImageAcquireResult()
|
||||||
{
|
{
|
||||||
m_image_acquire_result.reset();
|
m_image_acquire_result.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanSwapChain::ResizeSwapChain(u32 new_width, u32 new_height, float new_scale)
|
bool VulkanSwapChain::ResizeSwapChain(u32 new_width, u32 new_height, float new_scale)
|
||||||
{
|
{
|
||||||
|
ReleaseCurrentImage();
|
||||||
DestroySwapChainImages();
|
DestroySwapChainImages();
|
||||||
|
|
||||||
if (new_width != 0 && new_height != 0)
|
if (new_width != 0 && new_height != 0)
|
||||||
|
@ -657,6 +680,7 @@ bool VulkanSwapChain::SetPresentMode(VkPresentModeKHR present_mode)
|
||||||
|
|
||||||
// Recreate the swap chain with the new present mode.
|
// Recreate the swap chain with the new present mode.
|
||||||
VERBOSE_LOG("Recreating swap chain to change present mode.");
|
VERBOSE_LOG("Recreating swap chain to change present mode.");
|
||||||
|
ReleaseCurrentImage();
|
||||||
DestroySwapChainImages();
|
DestroySwapChainImages();
|
||||||
if (!CreateSwapChain())
|
if (!CreateSwapChain())
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
|
|
||||||
VkResult AcquireNextImage();
|
VkResult AcquireNextImage();
|
||||||
void ReleaseCurrentImage();
|
void ReleaseCurrentImage();
|
||||||
|
void ResetImageAcquireResult();
|
||||||
|
|
||||||
bool RecreateSurface(const WindowInfo& new_wi);
|
bool RecreateSurface(const WindowInfo& new_wi);
|
||||||
bool ResizeSwapChain(u32 new_width = 0, u32 new_height = 0, float new_scale = 1.0f);
|
bool ResizeSwapChain(u32 new_width = 0, u32 new_height = 0, float new_scale = 1.0f);
|
||||||
|
|
Loading…
Reference in a new issue