AI 修复横竖屏的问题
This commit is contained in:
@@ -54,9 +54,13 @@ void handle_cmd(android_app *pApp, int32_t cmd) {
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
aout << "APP_CMD_INIT_WINDOW" << std::endl;
|
||||
DebugLog::log("handle_cmd APP_CMD_INIT_WINDOW: calling onWindowInit()");
|
||||
if (g_Application != nullptr) {
|
||||
g_Application->onWindowInit();
|
||||
DebugLog::log("handle_cmd APP_CMD_INIT_WINDOW: onWindowInit() returned, isInited=%d",
|
||||
(int)g_Application->isInited());
|
||||
} else {
|
||||
DebugLog::log("handle_cmd APP_CMD_INIT_WINDOW: g_Application is null, skipping");
|
||||
}
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
aout << "APP_CMD_TERM_WINDOW" << std::endl;
|
||||
|
||||
+63
-10
@@ -112,9 +112,12 @@ void Application::initVulkan()
|
||||
createSyncObjects(); // 创建同步对象
|
||||
_lastDrawFrameTime = getCurrentTimeMillis();
|
||||
_applicationInited = true;
|
||||
// The first branch above already built all of the window-dependent
|
||||
// objects. Mark _sceondInited so we don't fall into the recovery
|
||||
// branch below and leak a second copy of surface/swapChain/etc.
|
||||
_sceondInited = true;
|
||||
}
|
||||
|
||||
if (!_sceondInited) {
|
||||
else if (!_sceondInited) {
|
||||
createSurface();
|
||||
createSwapChain();
|
||||
createImageViews();
|
||||
@@ -155,8 +158,14 @@ void Application::cleanupForWindowLost()
|
||||
(int)_applicationInited, (int)_sceondInited);
|
||||
return;
|
||||
}
|
||||
FACE_DBG_LOG("cleanupForWindowLost: begin (imageCount=%zu MAX_FRAMES_IN_FLIGHT=%d)",
|
||||
swapChainImages.size(), MAX_FRAMES_IN_FLIGHT);
|
||||
FACE_DBG_LOG("cleanupForWindowLost: begin (imageCount=%zu MAX_FRAMES_IN_FLIGHT=%d extent=%ux%u format=%d)",
|
||||
swapChainImages.size(), MAX_FRAMES_IN_FLIGHT,
|
||||
swapChainExtent.width, swapChainExtent.height, (int)swapChainImageFormat);
|
||||
|
||||
// Snapshot before we destroy the swapchain so reinitForNewWindow() can
|
||||
// decide whether the new swapchain needs renderPass / pipelines rebuilt.
|
||||
_prevSwapChainExtent = swapChainExtent;
|
||||
_prevSwapChainImageFormat = swapChainImageFormat;
|
||||
|
||||
// Block until GPU is no longer using any of the resources we are about
|
||||
// to destroy. Anything weaker than this risks hitting VK_ERROR_DEVICE_LOST
|
||||
@@ -222,29 +231,73 @@ void Application::cleanupForWindowLost()
|
||||
FACE_DBG_LOG("cleanupForWindowLost: done");
|
||||
}
|
||||
|
||||
void Application::reinitForNewWindow()
|
||||
bool Application::reinitForNewWindow()
|
||||
{
|
||||
if (!_applicationInited) {
|
||||
FACE_DBG_LOG("reinitForNewWindow: skip, _applicationInited=0 (must go through initVulkan first)");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (_sceondInited) {
|
||||
FACE_DBG_LOG("reinitForNewWindow: skip, already _sceondInited=1");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
FACE_DBG_LOG("reinitForNewWindow: begin");
|
||||
FACE_DBG_LOG("reinitForNewWindow: begin (prev extent=%ux%u format=%d)",
|
||||
_prevSwapChainExtent.width, _prevSwapChainExtent.height,
|
||||
(int)_prevSwapChainImageFormat);
|
||||
|
||||
createSurface();
|
||||
createSwapChain();
|
||||
|
||||
const bool extentChanged = (swapChainExtent.width != _prevSwapChainExtent.width) ||
|
||||
(swapChainExtent.height != _prevSwapChainExtent.height);
|
||||
const bool formatChanged = (swapChainImageFormat != _prevSwapChainImageFormat);
|
||||
const bool swapchainIncompatible = extentChanged || formatChanged;
|
||||
|
||||
if (formatChanged) {
|
||||
// renderPass bakes in swapChainImageFormat, so it must be rebuilt
|
||||
// when the surface chose a different format. The old Application
|
||||
// graphicsPipeline is tied to the old renderPass, so destroy it
|
||||
// first to make the handle invalidation explicit.
|
||||
FACE_DBG_LOG("reinitForNewWindow: format changed (%d -> %d), rebuilding renderPass",
|
||||
(int)_prevSwapChainImageFormat, (int)swapChainImageFormat);
|
||||
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;
|
||||
}
|
||||
createRenderPass();
|
||||
createPipelineLayout();
|
||||
createGraphicsPipeline();
|
||||
} else if (extentChanged) {
|
||||
// renderPass is still fine, but the Application pipeline has a static
|
||||
// viewport baked to the old extent and must be rebuilt.
|
||||
FACE_DBG_LOG("reinitForNewWindow: extent changed (%ux%u -> %ux%u), rebuilding graphicsPipeline",
|
||||
_prevSwapChainExtent.width, _prevSwapChainExtent.height,
|
||||
swapChainExtent.width, swapChainExtent.height);
|
||||
if (graphicsPipeline != VK_NULL_HANDLE) {
|
||||
vkDestroyPipeline(device, graphicsPipeline, nullptr);
|
||||
graphicsPipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
createGraphicsPipeline();
|
||||
}
|
||||
|
||||
createImageViews();
|
||||
createFramebuffers();
|
||||
createCommandBuffer();
|
||||
createSyncObjects();
|
||||
|
||||
_sceondInited = true;
|
||||
FACE_DBG_LOG("reinitForNewWindow: done (imageCount=%zu extent=%ux%u MAX_FRAMES_IN_FLIGHT=%d)",
|
||||
FACE_DBG_LOG("reinitForNewWindow: done (imageCount=%zu extent=%ux%u format=%d MAX_FRAMES_IN_FLIGHT=%d swapchainIncompatible=%d)",
|
||||
swapChainImages.size(), swapChainExtent.width, swapChainExtent.height,
|
||||
MAX_FRAMES_IN_FLIGHT);
|
||||
(int)swapChainImageFormat, MAX_FRAMES_IN_FLIGHT, (int)swapchainIncompatible);
|
||||
return swapchainIncompatible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+13
-1
@@ -90,7 +90,19 @@ public:
|
||||
|
||||
// Rebuild the window-dependent Vulkan objects torn down above.
|
||||
// Safe to call only after cleanupForWindowLost().
|
||||
void reinitForNewWindow();
|
||||
// Returns true when the new swapchain's extent or format differs from the
|
||||
// one in use before cleanupForWindowLost(). When true, any pipeline baked
|
||||
// with a static viewport/scissor from swapChainExtent -- including the
|
||||
// FaceApp pipelines -- must be destroyed and recreated against the new
|
||||
// renderPass / extent. Application's own renderPass + graphicsPipeline are
|
||||
// already handled internally.
|
||||
bool reinitForNewWindow();
|
||||
|
||||
// Extent / format captured by the most recent cleanupForWindowLost().
|
||||
// Used by reinitForNewWindow() to decide whether renderPass / pipelines
|
||||
// must be rebuilt against the new swapchain.
|
||||
VkExtent2D _prevSwapChainExtent = {0, 0};
|
||||
VkFormat _prevSwapChainImageFormat = VK_FORMAT_UNDEFINED;
|
||||
|
||||
protected:
|
||||
void loadTexture(std::string path, Texture& tex, bool srgb, VkCommandPool pool);
|
||||
|
||||
+34
-3
@@ -9,8 +9,10 @@
|
||||
#ifndef _WIN32
|
||||
#include "../app/src/main/cpp/DebugLog.h"
|
||||
#define FACE_DBG_LOG(...) DebugLog::log(__VA_ARGS__)
|
||||
#define FACE_DBG_LOG_THROTTLED(key, ...) DebugLog::log_throttled(key, __VA_ARGS__)
|
||||
#else
|
||||
#define FACE_DBG_LOG(...) ((void)0)
|
||||
#define FACE_DBG_LOG_THROTTLED(key, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -906,12 +908,18 @@ void FaceApp::onWindowInit()
|
||||
} else {
|
||||
// Recovery path after an earlier onWindowLost. Rebuild only the
|
||||
// window-dependent Vulkan objects; keep renderPass / pipelines /
|
||||
// FaceApp GPU resources intact.
|
||||
// FaceApp GPU resources intact unless the new swapchain is
|
||||
// incompatible (e.g. rotation changed extent).
|
||||
std::unique_lock<std::mutex> lk_point(mtx_point);
|
||||
std::unique_lock<std::mutex> lk_motion(changeMotionMtx);
|
||||
std::unique_lock<std::mutex> lk_tex(createTextureMtx);
|
||||
|
||||
Application::reinitForNewWindow();
|
||||
bool swapchainIncompatible = Application::reinitForNewWindow();
|
||||
|
||||
if (swapchainIncompatible && _faceAppInited) {
|
||||
FACE_DBG_LOG("FaceApp::onWindowInit: swapchain incompatible, rebuilding FaceApp pipelines");
|
||||
recreatePipelinesForSwapchain();
|
||||
}
|
||||
|
||||
if (!_secondfaceAppInited) {
|
||||
_secondfaceAppInited = true;
|
||||
@@ -925,6 +933,29 @@ void FaceApp::onWindowInit()
|
||||
(int)_secondfaceAppInited, (int)_running);
|
||||
}
|
||||
|
||||
void FaceApp::recreatePipelinesForSwapchain()
|
||||
{
|
||||
// Destroy the two FaceApp pipelines. Layouts / descriptor set layouts are
|
||||
// swapchain-independent and kept as-is so existing descriptor sets keep
|
||||
// pointing at the same texture/uniform resources.
|
||||
if (m_graphicsPipeline != VK_NULL_HANDLE) {
|
||||
vkDestroyPipeline(device, m_graphicsPipeline, nullptr);
|
||||
m_graphicsPipeline = VK_NULL_HANDLE;
|
||||
}
|
||||
if (m_graphicsPipeline_bg != VK_NULL_HANDLE) {
|
||||
vkDestroyPipeline(device, m_graphicsPipeline_bg, nullptr);
|
||||
m_graphicsPipeline_bg = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
// Recreate against the fresh renderPass (if format changed) and the new
|
||||
// swapChainExtent (viewport/scissor are baked statically into these).
|
||||
create_face_pipelines();
|
||||
create_pipelines_bg();
|
||||
|
||||
FACE_DBG_LOG("FaceApp::recreatePipelinesForSwapchain: rebuilt for extent=%ux%u",
|
||||
swapChainExtent.width, swapChainExtent.height);
|
||||
}
|
||||
|
||||
void FaceApp::update_uniform_buffers()
|
||||
{
|
||||
uint32_t width = 480;
|
||||
@@ -1637,7 +1668,7 @@ Motion FaceApp::getMotionByName(string name)
|
||||
|
||||
void FaceApp::changeMotionList(vector<string> motions, AnimationFinishedCallback callback, bool loop)
|
||||
{
|
||||
DebugLog::log_throttled("FaceApp.changeMotionList",
|
||||
FACE_DBG_LOG_THROTTLED("FaceApp.changeMotionList",
|
||||
"FaceApp::changeMotionList called count=%zu loop=%d _isLoadMotion=%d",
|
||||
motions.size(), (int)loop, (int)_isLoadMotion);
|
||||
if (_isLoadMotion)
|
||||
|
||||
+10
-1
@@ -191,8 +191,17 @@ public:
|
||||
|
||||
// Called from main thread in response to APP_CMD_INIT_WINDOW.
|
||||
// Does the full first-time initVulkan() on the very first call, and a
|
||||
// lightweight swapchain/surface rebuild on subsequent calls.
|
||||
// lightweight swapchain/surface rebuild on subsequent calls. When the
|
||||
// new swapchain's extent or format differs from the previous one, the
|
||||
// FaceApp pipelines (baked with static viewport / old renderPass) are
|
||||
// also destroyed and recreated via recreatePipelinesForSwapchain().
|
||||
void onWindowInit();
|
||||
|
||||
// Destroy and recreate m_graphicsPipeline / m_graphicsPipeline_bg so they
|
||||
// match the current renderPass and swapChainExtent. Descriptor set layouts,
|
||||
// pipeline layouts, vertex/index buffers, uniform buffers and textures are
|
||||
// all kept. Must be called with device idle and the FaceApp mutexes held.
|
||||
void recreatePipelinesForSwapchain();
|
||||
void loadMotionThread();
|
||||
std::thread worker_;
|
||||
bool _isLoadMotion = false;
|
||||
|
||||
Reference in New Issue
Block a user