Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6535a2c26a | ||
|
|
36d7d65a0a |
@@ -191,8 +191,38 @@ void android_main(struct android_app *pApp) {
|
|||||||
}
|
}
|
||||||
} while (!pApp->destroyRequested);
|
} while (!pApp->destroyRequested);
|
||||||
DebugLog::log("android_main: destroyRequested, running cleanup");
|
DebugLog::log("android_main: destroyRequested, running cleanup");
|
||||||
|
// ⚠️ 不要在这里调 cleanupSecondInit()。
|
||||||
|
//
|
||||||
|
// 在 Android 上,Activity 销毁(APP_CMD_DESTROY) 之前已经先收到了
|
||||||
|
// APP_CMD_TERM_WINDOW,handle_cmd 里走的是 onWindowLost()
|
||||||
|
// → Application::cleanupForWindowLost():销毁 swapChain / surface /
|
||||||
|
// framebuffers / imageViews / commandBuffers / 同步对象,但故意保留
|
||||||
|
// renderPass / pipelineLayout / graphicsPipeline,以便下一次进入
|
||||||
|
// Activity 时 reinitForNewWindow() 在 extent/format 不变的情况下
|
||||||
|
// 直接复用,省下重建 RenderPass / 重新编译 Pipeline 的开销。
|
||||||
|
//
|
||||||
|
// 而 cleanupSecondInit() 是 Windows 路径
|
||||||
|
// (mainLoop → cleanupSecondInit → initVulkan → mainLoop) 的对偶——
|
||||||
|
// 它会把 renderPass / pipelineLayout / graphicsPipeline 全部销毁。
|
||||||
|
// 又因为 g_Application 是一个跨 Activity 存活的全局 FaceApp 实例
|
||||||
|
// (android_main 入口处只在 g_Application == nullptr 时才 new),
|
||||||
|
// _applicationInited 也不会被复位;
|
||||||
|
// 下一次同一进程内进入另一个继承自 FaceActivity 的 Activity 时,
|
||||||
|
// onWindowInit() 看到 _applicationInited=1 走恢复分支调用
|
||||||
|
// reinitForNewWindow(),extent/format 与上次相同(480x480 / 同 format)
|
||||||
|
// 时**不会**重建 renderPass / pipelineLayout / graphicsPipeline——
|
||||||
|
// 用着已经被销毁的 renderPass 句柄继续 createFramebuffers() →
|
||||||
|
// recordCommandBuffer() → vkCmdBeginRenderPass(),
|
||||||
|
// Mali 驱动 (libGLES_mali) 在校验层后解引用已释放的 RenderPass 内部
|
||||||
|
// 数据,触发 SIGSEGV / si_addr=0x4
|
||||||
|
// (recordCommandBuffer + 0xBC,正好是 vkCmdBeginRenderPass)。
|
||||||
|
//
|
||||||
|
// 解决办法:android_main 退出时只信任 cleanupForWindowLost 已经做的
|
||||||
|
// 那部分清理,不再额外调 cleanupSecondInit(),让 renderPass /
|
||||||
|
// pipelineLayout / graphicsPipeline / FaceApp 的 m_graphicsPipeline*
|
||||||
|
// 都能存活到下一次 android_main 重新进来被复用。
|
||||||
//application.cleanup();
|
//application.cleanup();
|
||||||
g_Application->cleanupSecondInit();
|
//g_Application->cleanupSecondInit();
|
||||||
g_Application->clearnSecondFaceApp();
|
g_Application->clearnSecondFaceApp();
|
||||||
DebugLog::log("android_main: exit");
|
DebugLog::log("android_main: exit");
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-7
@@ -136,14 +136,55 @@ void Application::initVulkan()
|
|||||||
|
|
||||||
void Application::cleanupSecondInit()
|
void Application::cleanupSecondInit()
|
||||||
{
|
{
|
||||||
vkDestroySwapchainKHR(device, swapChain, nullptr);
|
// ★ 幂等:销毁后立刻把句柄置 VK_NULL_HANDLE / 清空 vector。
|
||||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
//
|
||||||
vkDestroyPipeline(device, graphicsPipeline, nullptr);
|
// 这个函数过去在 Android 路径 (android_main 退出) 上被错误地调用过;
|
||||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
// 由于销毁后没有清零句柄,紧接着重新进入的 reinitForNewWindow() 在
|
||||||
vkDestroyRenderPass(device, renderPass, nullptr);
|
// extent/format 不变时会跳过重建,让 framebuffer / drawFrame 在
|
||||||
for (auto imageView : swapChainImageViews) {
|
// 已经销毁的 renderPass 上继续工作,最终在
|
||||||
vkDestroyImageView(device, imageView, nullptr);
|
// vkCmdBeginRenderPass 内部 (libGLES_mali) 触发 SIGSEGV。
|
||||||
|
//
|
||||||
|
// 现在 android_main 退出路径已经不再调本函数;本函数只剩 Windows
|
||||||
|
// 路径 (mainLoop → cleanupSecondInit → initVulkan 的"二次 session"
|
||||||
|
// 复用) 在用。把它写成幂等的可以兜住将来任何对它的误用。
|
||||||
|
FACE_DBG_LOG("cleanupSecondInit: begin (swapChain=%s surface=%s renderPass=%s pipelineLayout=%s graphicsPipeline=%s imageViews=%zu framebuffers=%zu)",
|
||||||
|
swapChain == VK_NULL_HANDLE ? "null" : "live",
|
||||||
|
surface == VK_NULL_HANDLE ? "null" : "live",
|
||||||
|
renderPass == VK_NULL_HANDLE ? "null" : "live",
|
||||||
|
pipelineLayout == VK_NULL_HANDLE ? "null" : "live",
|
||||||
|
graphicsPipeline == VK_NULL_HANDLE ? "null" : "live",
|
||||||
|
swapChainImageViews.size(), swapChainFramebuffers.size());
|
||||||
|
|
||||||
|
if (device != VK_NULL_HANDLE) {
|
||||||
|
vkDeviceWaitIdle(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (swapChain != VK_NULL_HANDLE) {
|
||||||
|
vkDestroySwapchainKHR(device, swapChain, nullptr);
|
||||||
|
swapChain = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (surface != VK_NULL_HANDLE) {
|
||||||
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||||
|
surface = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (graphicsPipeline != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipeline(device, graphicsPipeline, nullptr);
|
||||||
|
graphicsPipeline = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (pipelineLayout != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||||
|
pipelineLayout = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
if (renderPass != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyRenderPass(device, renderPass, nullptr);
|
||||||
|
renderPass = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
for (auto imageView : swapChainImageViews) {
|
||||||
|
if (imageView != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyImageView(device, imageView, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swapChainImageViews.clear();
|
||||||
for (auto framebuffer : swapChainFramebuffers)
|
for (auto framebuffer : swapChainFramebuffers)
|
||||||
{
|
{
|
||||||
if (framebuffer != VK_NULL_HANDLE)
|
if (framebuffer != VK_NULL_HANDLE)
|
||||||
@@ -152,6 +193,7 @@ void Application::cleanupSecondInit()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
swapChainFramebuffers.clear();
|
swapChainFramebuffers.clear();
|
||||||
|
swapChainImages.clear();
|
||||||
|
|
||||||
_sceondInited = false;
|
_sceondInited = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user