[Fix] (MG_Backend/DirectVulkan): separate EGL surface lifecycle

This commit is contained in:
2026-07-03 12:20:40 +08:00
parent afdbf0a194
commit 45f1a13cc3
4 changed files with 147 additions and 49 deletions
@@ -2021,37 +2021,7 @@ void main() {
}
s_vkCmdDrawIndexedIndirectCount = nullptr;
if (m_instance != VK_NULL_HANDLE && m_surface != VK_NULL_HANDLE) {
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
m_surface = VK_NULL_HANDLE;
}
#if defined(VK_USE_PLATFORM_METAL_EXT)
if (m_platformLibrary != nullptr) {
Release(reinterpret_cast<id>(m_platformLibrary));
m_platformLibrary = nullptr;
}
if (m_platformDisplay != nullptr) {
Release(reinterpret_cast<id>(m_platformDisplay));
m_platformDisplay = nullptr;
}
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
if (m_platformDisplay != nullptr) {
using XCloseDisplayFn = int (*)(Display*);
auto* closeDisplay = reinterpret_cast<XCloseDisplayFn>(m_platformCloseDisplay);
if (closeDisplay) {
closeDisplay(static_cast<Display*>(m_platformDisplay));
}
m_platformDisplay = nullptr;
}
m_platformCloseDisplay = nullptr;
if (m_platformLibrary != nullptr) {
dlclose(m_platformLibrary);
m_platformLibrary = nullptr;
}
#endif
DestroySurface();
if (m_debugMessenger != VK_NULL_HANDLE) {
DestroyDebugMessenger();
@@ -2065,6 +2035,67 @@ void main() {
MGLOG_I("VulkanRenderer shut down completed");
}
void VulkanRenderer::BindSurface(NativeWindowType window, const VulkanRendererConfig& cfg) {
if (m_instance == VK_NULL_HANDLE) {
m_window = window;
m_config = cfg;
Initialize();
return;
}
if (m_device != VK_NULL_HANDLE) {
VK_VERIFY(vkDeviceWaitIdle(m_device));
}
ReleaseSurface();
m_window = window;
m_config.SurfaceWidth = std::max<Uint32>(cfg.SurfaceWidth, 1);
m_config.SurfaceHeight = std::max<Uint32>(cfg.SurfaceHeight, 1);
CreateSurface();
const auto queueFamilies = GetQueueFamilyFromPhysicalDevice(m_physicalDevice.handle);
const Int presentFamily =
GetPresentQueueFamilyIndex(m_physicalDevice, m_surface, queueFamilies,
m_physicalDevice.queueFamilies.presentFamily);
MOBILEGL_ASSERT(presentFamily == m_physicalDevice.queueFamilies.presentFamily,
"BindSurface: new EGL surface requires a different Vulkan present queue family");
RecreateSwapchain();
VkResult acquireResult =
m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
if (acquireResult == VK_ERROR_OUT_OF_DATE_KHR || acquireResult == VK_SUBOPTIMAL_KHR) {
RecreateSwapchain();
acquireResult =
m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
}
VK_VERIFY(acquireResult, "BindSurface, WaitAndAcquireNextImage");
if (m_textureManager) {
m_textureManager->BeginFrame(m_frameContext.GetCurrentFrameIndex());
}
m_bufferManager.BeginFrame(m_frameContext.GetCurrentFrameIndex());
m_transientVertexIndexBufferSlicesThisFrame.clear();
m_swapchainResizeRequested = false;
}
void VulkanRenderer::ReleaseSurface() {
if (m_surface == VK_NULL_HANDLE && m_swapchainObject.GetHandle() == VK_NULL_HANDLE) {
return;
}
if (m_device != VK_NULL_HANDLE) {
VK_VERIFY(vkDeviceWaitIdle(m_device));
DestroyDeferredDepthMipmapCleanup();
if (m_renderPassManager) {
ShutdownSwapchain();
} else {
m_swapchainObject.Shutdown(m_device);
}
}
DestroySurface();
m_swapchainResizeRequested = false;
m_imageIndexAcquired = 0;
}
Bool VulkanRenderer::UploadAndBindVertexBuffers(
VkCommandBuffer commandBuffer, const MG_State::GLState::VertexArrayObject& vao, const DrawCmdParam& drawParams) {
auto& vertexInputState = m_vertexInputStateFactory->GetOrCreateVertexInputState(vao);
@@ -6013,6 +6044,42 @@ void main() {
#endif
}
void VulkanRenderer::DestroySurface() {
if (m_instance != VK_NULL_HANDLE && m_surface != VK_NULL_HANDLE) {
vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
m_surface = VK_NULL_HANDLE;
}
#if defined(VK_USE_PLATFORM_METAL_EXT)
if (m_platformLibrary != nullptr) {
Release(reinterpret_cast<id>(m_platformLibrary));
m_platformLibrary = nullptr;
}
if (m_platformDisplay != nullptr) {
Release(reinterpret_cast<id>(m_platformDisplay));
m_platformDisplay = nullptr;
}
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
if (m_platformDisplay != nullptr) {
using XCloseDisplayFn = int (*)(Display*);
auto* closeDisplay = reinterpret_cast<XCloseDisplayFn>(m_platformCloseDisplay);
if (closeDisplay) {
closeDisplay(static_cast<Display*>(m_platformDisplay));
}
m_platformDisplay = nullptr;
}
m_platformCloseDisplay = nullptr;
if (m_platformLibrary != nullptr) {
dlclose(m_platformLibrary);
m_platformLibrary = nullptr;
}
#endif
m_window = 0;
}
Vector<VkQueueFamilyProperties> VulkanRenderer::GetQueueFamilyFromPhysicalDevice(VkPhysicalDevice device) {
Uint32 queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);