Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6535a2c26a | ||
|
|
36d7d65a0a |
@@ -191,8 +191,38 @@ void android_main(struct android_app *pApp) {
|
||||
}
|
||||
} while (!pApp->destroyRequested);
|
||||
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();
|
||||
g_Application->cleanupSecondInit();
|
||||
//g_Application->cleanupSecondInit();
|
||||
g_Application->clearnSecondFaceApp();
|
||||
DebugLog::log("android_main: exit");
|
||||
}
|
||||
|
||||
+49
-7
@@ -136,14 +136,55 @@ void Application::initVulkan()
|
||||
|
||||
void Application::cleanupSecondInit()
|
||||
{
|
||||
vkDestroySwapchainKHR(device, swapChain, nullptr);
|
||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||
vkDestroyPipeline(device, graphicsPipeline, nullptr);
|
||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||
vkDestroyRenderPass(device, renderPass, nullptr);
|
||||
for (auto imageView : swapChainImageViews) {
|
||||
vkDestroyImageView(device, imageView, nullptr);
|
||||
// ★ 幂等:销毁后立刻把句柄置 VK_NULL_HANDLE / 清空 vector。
|
||||
//
|
||||
// 这个函数过去在 Android 路径 (android_main 退出) 上被错误地调用过;
|
||||
// 由于销毁后没有清零句柄,紧接着重新进入的 reinitForNewWindow() 在
|
||||
// extent/format 不变时会跳过重建,让 framebuffer / drawFrame 在
|
||||
// 已经销毁的 renderPass 上继续工作,最终在
|
||||
// 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)
|
||||
{
|
||||
if (framebuffer != VK_NULL_HANDLE)
|
||||
@@ -152,6 +193,7 @@ void Application::cleanupSecondInit()
|
||||
}
|
||||
}
|
||||
swapChainFramebuffers.clear();
|
||||
swapChainImages.clear();
|
||||
|
||||
_sceondInited = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user