mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-05 03:48:01 +00:00
Add failure handling to vulkan swapchain creation.
* If a swapchain fails to create, we'll just continue and not render anything. we'll try to recreate a few times and also on resize, in case the failure is transient.
This commit is contained in:
@@ -42,6 +42,10 @@ VulkanReplay::OutputWindow::OutputWindow()
|
||||
|
||||
fresh = true;
|
||||
|
||||
hasDepth = false;
|
||||
|
||||
failures = recreatePause = 0;
|
||||
|
||||
bb = VK_NULL_HANDLE;
|
||||
bbview = VK_NULL_HANDLE;
|
||||
fb = VK_NULL_HANDLE;
|
||||
@@ -159,6 +163,8 @@ void VulkanReplay::OutputWindow::Create(WrappedVulkan *driver, VkDevice device,
|
||||
VkInstance inst = driver->GetInstance();
|
||||
VkPhysicalDevice phys = driver->GetPhysDev();
|
||||
|
||||
hasDepth = depth;
|
||||
|
||||
// save the old swapchain so it isn't destroyed
|
||||
VkSwapchainKHR old = swap;
|
||||
swap = VK_NULL_HANDLE;
|
||||
@@ -315,14 +321,38 @@ void VulkanReplay::OutputWindow::Create(WrappedVulkan *driver, VkDevice device,
|
||||
vkr = vt->CreateSwapchainKHR(Unwrap(device), &swapInfo, NULL, &swap);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
GetResourceManager()->WrapResource(Unwrap(device), swap);
|
||||
|
||||
if(old != VK_NULL_HANDLE)
|
||||
{
|
||||
vt->DestroySwapchainKHR(Unwrap(device), Unwrap(old), NULL);
|
||||
GetResourceManager()->ReleaseWrappedResource(old);
|
||||
}
|
||||
|
||||
if(swap == VK_NULL_HANDLE)
|
||||
{
|
||||
RDCERR("Failed to create swapchain. %d consecutive failures!", failures);
|
||||
failures++;
|
||||
|
||||
// do some sort of backoff.
|
||||
|
||||
// the first time, try to recreate again next frame
|
||||
if(failures == 1)
|
||||
recreatePause = 0;
|
||||
// the next few times, wait 200 'frames' between attempts
|
||||
else if(failures < 10)
|
||||
recreatePause = 100;
|
||||
// otherwise, only reattempt very infrequently. A resize will
|
||||
// always retrigger a recreate, so ew probably don't want to
|
||||
// try again
|
||||
else
|
||||
recreatePause = 1000;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
failures = 0;
|
||||
|
||||
GetResourceManager()->WrapResource(Unwrap(device), swap);
|
||||
|
||||
vkr = vt->GetSwapchainImagesKHR(Unwrap(device), Unwrap(swap), &numImgs, NULL);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
@@ -1034,6 +1064,11 @@ bool VulkanReplay::RenderTexture(TextureDisplay cfg)
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return false;
|
||||
|
||||
VkClearValue clearval = {};
|
||||
VkRenderPassBeginInfo rpbegin = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
@@ -1435,6 +1470,11 @@ void VulkanReplay::RenderCheckerboard(Vec3f light, Vec3f dark)
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
const VkLayerDispatchTable *vt = ObjDisp(dev);
|
||||
@@ -1503,6 +1543,11 @@ void VulkanReplay::RenderHighlightBox(float w, float h, float scale)
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
const VkLayerDispatchTable *vt = ObjDisp(dev);
|
||||
@@ -1628,6 +1673,11 @@ void VulkanReplay::RenderMesh(uint32_t eventID, const vector<MeshFormat> &second
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
const VkLayerDispatchTable *vt = ObjDisp(dev);
|
||||
@@ -2680,15 +2730,19 @@ bool VulkanReplay::CheckResizeOutputWindow(uint64_t id)
|
||||
outw.height = h;
|
||||
|
||||
if(outw.width > 0 && outw.height > 0)
|
||||
{
|
||||
bool depth = (outw.dsimg != VK_NULL_HANDLE);
|
||||
|
||||
outw.Create(m_pDriver, m_pDriver->GetDev(), depth);
|
||||
}
|
||||
outw.Create(m_pDriver, m_pDriver->GetDev(), outw.hasDepth);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(outw.swap == VK_NULL_HANDLE && outw.width > 0 && outw.height > 0)
|
||||
{
|
||||
if(outw.recreatePause <= 0)
|
||||
outw.Create(m_pDriver, m_pDriver->GetDev(), outw.hasDepth);
|
||||
else
|
||||
outw.recreatePause--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2703,6 +2757,11 @@ void VulkanReplay::BindOutputWindow(uint64_t id, bool depth)
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
m_DebugWidth = (int32_t)outw.width;
|
||||
m_DebugHeight = (int32_t)outw.height;
|
||||
|
||||
@@ -2799,6 +2858,11 @@ void VulkanReplay::ClearOutputWindowColour(uint64_t id, float col[4])
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
const VkLayerDispatchTable *vt = ObjDisp(dev);
|
||||
@@ -2844,6 +2908,11 @@ void VulkanReplay::ClearOutputWindowDepth(uint64_t id, float depth, uint8_t sten
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
const VkLayerDispatchTable *vt = ObjDisp(dev);
|
||||
@@ -2892,6 +2961,11 @@ void VulkanReplay::FlipOutputWindow(uint64_t id)
|
||||
|
||||
OutputWindow &outw = it->second;
|
||||
|
||||
// if the swapchain failed to create, do nothing. We will try to recreate it
|
||||
// again in CheckResizeOutputWindow (once per render 'frame')
|
||||
if(outw.swap == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
VkCommandBuffer cmd = m_pDriver->GetNextCmd();
|
||||
const VkLayerDispatchTable *vt = ObjDisp(dev);
|
||||
|
||||
@@ -227,6 +227,11 @@ private:
|
||||
|
||||
uint32_t width, height;
|
||||
|
||||
bool hasDepth;
|
||||
|
||||
int failures;
|
||||
int recreatePause;
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
VkSwapchainKHR swap;
|
||||
uint32_t numImgs;
|
||||
|
||||
Reference in New Issue
Block a user