Vulkan: Recreate the swapchain if we get too many "out of date" frames.

Should help an issue on my Linux laptop with Intel GPU.
This commit is contained in:
Henrik Rydgård committed 2020-06-22 00:45:05 +02:00
1 parent b45128025f
commit cd1d73436d
6 files changed
+33 -3

No files matched your search

+4
View File
@@ -34,6 +34,10 @@ public:
virtual void ThreadEnd() {}
virtual void StopThread() {}
// Useful for checks that need to be performed every frame.
// Should strive to get rid of these.
virtual void Poll() {}
virtual Draw::DrawContext *GetDrawContext() = 0;
};
+2
View File
@@ -1095,6 +1095,8 @@ void NativeRender(GraphicsContext *graphicsContext) {
NativeMessageReceived("gpu_resized", "");
}
#endif
} else {
graphicsContext->Poll();
}
ui_draw2d.PopDrawMatrix();
+11 -3
View File
@@ -143,9 +143,9 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
_assert_msg_(G3D, success, "Failed to compile preset shaders");
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager->SetInflightFrames(g_Config.iInflightFrames);
if (!renderManager->HasBackbuffers()) {
renderManager_ = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
if (!renderManager_->HasBackbuffers()) {
Shutdown();
return false;
}
@@ -166,6 +166,7 @@ void WindowsVulkanContext::Shutdown() {
delete g_Vulkan;
g_Vulkan = nullptr;
renderManager_ = nullptr;
finalize_glslang();
}
@@ -181,6 +182,13 @@ void WindowsVulkanContext::Resize() {
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, g_Vulkan->GetBackbufferWidth(), g_Vulkan->GetBackbufferHeight());
}
void WindowsVulkanContext::Poll() {
// Check for existing swapchain to avoid issues during shutdown.
if (g_Vulkan->GetSwapchain() && renderManager_->NeedsSwapchainRecreate()) {
Resize();
}
}
void *WindowsVulkanContext::GetAPIContext() {
return g_Vulkan;
}
+4
View File
@@ -21,6 +21,8 @@
#include "Windows/GPU/WindowsGraphicsContext.h"
#include "thin3d/thin3d.h"
class VulkanRenderManager;
class WindowsVulkanContext : public WindowsGraphicsContext {
public:
WindowsVulkanContext() : draw_(nullptr) {}
@@ -29,11 +31,13 @@ public:
void SwapInterval(int interval) override {}
void SwapBuffers() override {}
void Resize() override;
void Poll() override;
void *GetAPIContext();
Draw::DrawContext *GetDrawContext() override { return draw_; }
private:
Draw::DrawContext *draw_;
VulkanRenderManager *renderManager_ = nullptr;
};
@@ -209,6 +209,8 @@ void VulkanRenderManager::CreateBackbuffers() {
newInflightFrames_ = -1;
}
outOfDateFrames_ = 0;
// Start the thread.
if (useThread_ && HasBackbuffers()) {
run_ = true;
@@ -1029,11 +1031,14 @@ void VulkanRenderManager::BeginSubmitFrame(int frame) {
if (res == VK_SUBOPTIMAL_KHR) {
// Hopefully the resize will happen shortly. Ignore - one frame might look bad or something.
WLOG("VK_SUBOPTIMAL_KHR returned - ignoring");
outOfDateFrames_++;
} else if (res == VK_ERROR_OUT_OF_DATE_KHR) {
WLOG("VK_ERROR_OUT_OF_DATE_KHR returned - not presenting");
frameData.skipSwap = true;
outOfDateFrames_++;
} else {
_assert_msg_(G3D, res == VK_SUCCESS, "vkAcquireNextImageKHR failed! result=%s", VulkanResultToString(res));
outOfDateFrames_ = 0;
}
VkCommandBufferBeginInfo begin{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+7
View File
@@ -285,6 +285,11 @@ public:
return frameData_[vulkan_->GetCurFrame()].profile.profileSummary;
}
bool NeedsSwapchainRecreate() const {
// Accepting a few of these makes shutdown simpler.
return outOfDateFrames_ > VulkanContext::MAX_INFLIGHT_FRAMES;
}
private:
bool InitBackbufferFramebuffers(int width, int height);
bool InitDepthStencilBuffer(VkCommandBuffer cmd); // Used for non-buffered rendering.
@@ -337,6 +342,8 @@ private:
int newInflightFrames_ = -1;
int inflightFramesAtStart_ = 0;
int outOfDateFrames_ = 0;
// Submission time state
int curWidth_ = -1;
int curHeight_ = -1;