mirror of https://github.com/PCSX2/pcsx2.git
HostDisplay: Fix vsync getting lost on window changes
This commit is contained in:
parent
061fff6f17
commit
c74cc9bc12
|
@ -291,7 +291,7 @@ namespace Vulkan
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Context::Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
|
bool Context::Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
|
||||||
bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer)
|
bool vsync, bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer)
|
||||||
{
|
{
|
||||||
pxAssertMsg(!g_vulkan_context, "Has no current context");
|
pxAssertMsg(!g_vulkan_context, "Has no current context");
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ namespace Vulkan
|
||||||
if (!g_vulkan_context->CreateDevice(surface, enable_validation_layer, nullptr, 0, nullptr, 0, nullptr) ||
|
if (!g_vulkan_context->CreateDevice(surface, enable_validation_layer, nullptr, 0, nullptr, 0, nullptr) ||
|
||||||
!g_vulkan_context->CreateAllocator() || !g_vulkan_context->CreateGlobalDescriptorPool() ||
|
!g_vulkan_context->CreateAllocator() || !g_vulkan_context->CreateGlobalDescriptorPool() ||
|
||||||
!g_vulkan_context->CreateCommandBuffers() || !g_vulkan_context->CreateTextureStreamBuffer() ||
|
!g_vulkan_context->CreateCommandBuffers() || !g_vulkan_context->CreateTextureStreamBuffer() ||
|
||||||
(enable_surface && (*out_swap_chain = SwapChain::Create(wi_copy, surface, true)) == nullptr))
|
(enable_surface && (*out_swap_chain = SwapChain::Create(wi_copy, surface, vsync)) == nullptr))
|
||||||
{
|
{
|
||||||
// Since we are destroying the instance, we're also responsible for destroying the surface.
|
// Since we are destroying the instance, we're also responsible for destroying the surface.
|
||||||
if (surface != VK_NULL_HANDLE)
|
if (surface != VK_NULL_HANDLE)
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace Vulkan
|
||||||
|
|
||||||
// Creates a new context and sets it up as global.
|
// Creates a new context and sets it up as global.
|
||||||
static bool Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
|
static bool Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
|
||||||
bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer);
|
bool vsync, bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer);
|
||||||
|
|
||||||
// Destroys context.
|
// Destroys context.
|
||||||
static void Destroy();
|
static void Destroy();
|
||||||
|
|
|
@ -906,7 +906,7 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""),
|
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""),
|
||||||
Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false),
|
EmuConfig.GetEffectiveVsyncMode(), Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false),
|
||||||
Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
|
Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
|
||||||
{
|
{
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Failed to create host display device context."));
|
QMessageBox::critical(this, tr("Error"), tr("Failed to create host display device context."));
|
||||||
|
|
|
@ -205,10 +205,10 @@ bool D3D11HostDisplay::GetHostRefreshRate(float* refresh_rate)
|
||||||
|
|
||||||
void D3D11HostDisplay::SetVSync(VsyncMode mode)
|
void D3D11HostDisplay::SetVSync(VsyncMode mode)
|
||||||
{
|
{
|
||||||
m_vsync = mode;
|
m_vsync_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11HostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool threaded_presentation, bool debug_device)
|
bool D3D11HostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device)
|
||||||
{
|
{
|
||||||
UINT create_flags = 0;
|
UINT create_flags = 0;
|
||||||
if (debug_device)
|
if (debug_device)
|
||||||
|
@ -318,6 +318,7 @@ bool D3D11HostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view
|
||||||
}
|
}
|
||||||
|
|
||||||
m_window_info = wi;
|
m_window_info = wi;
|
||||||
|
m_vsync_mode = vsync;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +742,7 @@ void D3D11HostDisplay::EndPresent()
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
const UINT vsync_rate = static_cast<UINT>(m_vsync != VsyncMode::Off);
|
const UINT vsync_rate = static_cast<UINT>(m_vsync_mode != VsyncMode::Off);
|
||||||
if (vsync_rate == 0 && m_using_allow_tearing)
|
if (vsync_rate == 0 && m_using_allow_tearing)
|
||||||
m_swap_chain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
|
m_swap_chain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
|
||||||
else
|
else
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
bool HasRenderDevice() const override;
|
bool HasRenderDevice() const override;
|
||||||
bool HasRenderSurface() const override;
|
bool HasRenderSurface() const override;
|
||||||
|
|
||||||
bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool threaded_presentation, bool debug_device) override;
|
bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device) override;
|
||||||
bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) override;
|
bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) override;
|
||||||
void DestroyRenderDevice() override;
|
void DestroyRenderDevice() override;
|
||||||
|
|
||||||
|
@ -89,7 +89,6 @@ protected:
|
||||||
ComPtr<IDXGISwapChain> m_swap_chain;
|
ComPtr<IDXGISwapChain> m_swap_chain;
|
||||||
ComPtr<ID3D11RenderTargetView> m_swap_chain_rtv;
|
ComPtr<ID3D11RenderTargetView> m_swap_chain_rtv;
|
||||||
|
|
||||||
VsyncMode m_vsync = VsyncMode::Off;
|
|
||||||
bool m_allow_tearing_supported = false;
|
bool m_allow_tearing_supported = false;
|
||||||
bool m_using_flip_model_swap_chain = true;
|
bool m_using_flip_model_swap_chain = true;
|
||||||
bool m_using_allow_tearing = false;
|
bool m_using_allow_tearing = false;
|
||||||
|
|
|
@ -190,7 +190,7 @@ bool OpenGLHostDisplay::HasRenderSurface() const
|
||||||
return m_window_info.type != WindowInfo::Type::Surfaceless;
|
return m_window_info.type != WindowInfo::Type::Surfaceless;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool threaded_presentation, bool debug_device)
|
bool OpenGLHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device)
|
||||||
{
|
{
|
||||||
m_gl_context = GL::Context::Create(wi);
|
m_gl_context = GL::Context::Create(wi);
|
||||||
if (!m_gl_context)
|
if (!m_gl_context)
|
||||||
|
@ -201,17 +201,23 @@ bool OpenGLHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_vie
|
||||||
}
|
}
|
||||||
|
|
||||||
m_window_info = m_gl_context->GetWindowInfo();
|
m_window_info = m_gl_context->GetWindowInfo();
|
||||||
|
m_vsync_mode = vsync;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLHostDisplay::InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device)
|
bool OpenGLHostDisplay::InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device)
|
||||||
{
|
{
|
||||||
// Start with vsync off.
|
SetSwapInterval();
|
||||||
m_gl_context->SetSwapInterval(0);
|
|
||||||
GL::Program::ResetLastProgram();
|
GL::Program::ResetLastProgram();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLHostDisplay::SetSwapInterval()
|
||||||
|
{
|
||||||
|
const int interval = ((m_vsync_mode == VsyncMode::Adaptive) ? -1 : ((m_vsync_mode == VsyncMode::On) ? 1 : 0));
|
||||||
|
m_gl_context->SetSwapInterval(interval);
|
||||||
|
}
|
||||||
|
|
||||||
bool OpenGLHostDisplay::MakeRenderContextCurrent()
|
bool OpenGLHostDisplay::MakeRenderContextCurrent()
|
||||||
{
|
{
|
||||||
if (!m_gl_context->MakeCurrent())
|
if (!m_gl_context->MakeCurrent())
|
||||||
|
@ -220,6 +226,7 @@ bool OpenGLHostDisplay::MakeRenderContextCurrent()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetSwapInterval();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
bool HasRenderDevice() const override;
|
bool HasRenderDevice() const override;
|
||||||
bool HasRenderSurface() const override;
|
bool HasRenderSurface() const override;
|
||||||
|
|
||||||
bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool threaded_presentation, bool debug_device) override;
|
bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device) override;
|
||||||
bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) override;
|
bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) override;
|
||||||
void DestroyRenderDevice() override;
|
void DestroyRenderDevice() override;
|
||||||
|
|
||||||
|
@ -68,8 +68,8 @@ protected:
|
||||||
void DestroyImGuiContext() override;
|
void DestroyImGuiContext() override;
|
||||||
bool UpdateImGuiFontTexture() override;
|
bool UpdateImGuiFontTexture() override;
|
||||||
|
|
||||||
std::unique_ptr<GL::Context> m_gl_context;
|
void SetSwapInterval();
|
||||||
|
|
||||||
VsyncMode m_vsync_mode = VsyncMode::Off;
|
std::unique_ptr<GL::Context> m_gl_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ bool VulkanHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_swap_chain = Vulkan::SwapChain::Create(wi_copy, surface, false);
|
m_swap_chain = Vulkan::SwapChain::Create(wi_copy, surface, m_vsync_mode != VsyncMode::Off);
|
||||||
if (!m_swap_chain)
|
if (!m_swap_chain)
|
||||||
{
|
{
|
||||||
Console.Error("Failed to create swap chain");
|
Console.Error("Failed to create swap chain");
|
||||||
|
@ -216,29 +216,32 @@ void VulkanHostDisplay::UpdateTexture(
|
||||||
|
|
||||||
void VulkanHostDisplay::SetVSync(VsyncMode mode)
|
void VulkanHostDisplay::SetVSync(VsyncMode mode)
|
||||||
{
|
{
|
||||||
if (!m_swap_chain)
|
if (!m_swap_chain || m_vsync_mode == mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// This swap chain should not be used by the current buffer, thus safe to destroy.
|
// This swap chain should not be used by the current buffer, thus safe to destroy.
|
||||||
g_vulkan_context->WaitForGPUIdle();
|
g_vulkan_context->WaitForGPUIdle();
|
||||||
m_swap_chain->SetVSync(mode != VsyncMode::Off);
|
m_swap_chain->SetVSync(mode != VsyncMode::Off);
|
||||||
|
m_vsync_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanHostDisplay::CreateRenderDevice(
|
bool VulkanHostDisplay::CreateRenderDevice(
|
||||||
const WindowInfo& wi, std::string_view adapter_name, bool threaded_presentation, bool debug_device)
|
const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device)
|
||||||
{
|
{
|
||||||
// debug_device = true;
|
// debug_device = true;
|
||||||
|
|
||||||
WindowInfo local_wi(wi);
|
WindowInfo local_wi(wi);
|
||||||
if (!Vulkan::Context::Create(
|
if (!Vulkan::Context::Create(
|
||||||
adapter_name, &local_wi, &m_swap_chain, threaded_presentation, debug_device, debug_device))
|
adapter_name, &local_wi, &m_swap_chain, vsync != VsyncMode::Off, threaded_presentation, debug_device, debug_device))
|
||||||
{
|
{
|
||||||
Console.Error("Failed to create Vulkan context");
|
Console.Error("Failed to create Vulkan context");
|
||||||
m_window_info = {};
|
m_window_info = {};
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: This is assigned afterwards, because some platforms can modify the window info (e.g. Metal).
|
||||||
m_window_info = m_swap_chain ? m_swap_chain->GetWindowInfo() : local_wi;
|
m_window_info = m_swap_chain ? m_swap_chain->GetWindowInfo() : local_wi;
|
||||||
|
m_vsync_mode = vsync;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
bool HasRenderDevice() const override;
|
bool HasRenderDevice() const override;
|
||||||
bool HasRenderSurface() const override;
|
bool HasRenderSurface() const override;
|
||||||
|
|
||||||
bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool threaded_presentation, bool debug_device) override;
|
bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device) override;
|
||||||
bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) override;
|
bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) override;
|
||||||
void DestroyRenderDevice() override;
|
void DestroyRenderDevice() override;
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ public:
|
||||||
virtual bool HasRenderDevice() const = 0;
|
virtual bool HasRenderDevice() const = 0;
|
||||||
virtual bool HasRenderSurface() const = 0;
|
virtual bool HasRenderSurface() const = 0;
|
||||||
|
|
||||||
virtual bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool threaded_presentation, bool debug_device) = 0;
|
virtual bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, VsyncMode vsync, bool threaded_presentation, bool debug_device) = 0;
|
||||||
virtual bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) = 0;
|
virtual bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device) = 0;
|
||||||
virtual bool MakeRenderContextCurrent() = 0;
|
virtual bool MakeRenderContextCurrent() = 0;
|
||||||
virtual bool DoneRenderContextCurrent() = 0;
|
virtual bool DoneRenderContextCurrent() = 0;
|
||||||
|
@ -139,6 +139,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
WindowInfo m_window_info;
|
WindowInfo m_window_info;
|
||||||
Alignment m_display_alignment = Alignment::Center;
|
Alignment m_display_alignment = Alignment::Center;
|
||||||
|
VsyncMode m_vsync_mode = VsyncMode::Off;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Host
|
namespace Host
|
||||||
|
|
|
@ -120,7 +120,8 @@ HostDisplay* Host::AcquireHostDisplay(HostDisplay::RenderAPI api)
|
||||||
if (!s_host_display)
|
if (!s_host_display)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (!s_host_display->CreateRenderDevice(g_gs_window_info, GSConfig.Adapter, GSConfig.ThreadedPresentation, GSConfig.UseDebugDevice) ||
|
if (!s_host_display->CreateRenderDevice(g_gs_window_info, GSConfig.Adapter, EmuConfig.GetEffectiveVsyncMode(),
|
||||||
|
GSConfig.ThreadedPresentation, GSConfig.UseDebugDevice) ||
|
||||||
!s_host_display->InitializeRenderDevice(StringUtil::wxStringToUTF8String(EmuFolders::Cache.ToString()), GSConfig.UseDebugDevice) ||
|
!s_host_display->InitializeRenderDevice(StringUtil::wxStringToUTF8String(EmuFolders::Cache.ToString()), GSConfig.UseDebugDevice) ||
|
||||||
!ImGuiManager::Initialize())
|
!ImGuiManager::Initialize())
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue