AI 修复横竖屏的问题
This commit is contained in:
@@ -54,9 +54,13 @@ void handle_cmd(android_app *pApp, int32_t cmd) {
|
|||||||
case APP_CMD_INIT_WINDOW:
|
case APP_CMD_INIT_WINDOW:
|
||||||
aout << "APP_CMD_INIT_WINDOW" << std::endl;
|
aout << "APP_CMD_INIT_WINDOW" << std::endl;
|
||||||
DebugLog::log("handle_cmd APP_CMD_INIT_WINDOW: calling onWindowInit()");
|
DebugLog::log("handle_cmd APP_CMD_INIT_WINDOW: calling onWindowInit()");
|
||||||
g_Application->onWindowInit();
|
if (g_Application != nullptr) {
|
||||||
DebugLog::log("handle_cmd APP_CMD_INIT_WINDOW: onWindowInit() returned, isInited=%d",
|
g_Application->onWindowInit();
|
||||||
(int)g_Application->isInited());
|
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;
|
break;
|
||||||
case APP_CMD_TERM_WINDOW:
|
case APP_CMD_TERM_WINDOW:
|
||||||
aout << "APP_CMD_TERM_WINDOW" << std::endl;
|
aout << "APP_CMD_TERM_WINDOW" << std::endl;
|
||||||
|
|||||||
+63
-10
@@ -112,9 +112,12 @@ void Application::initVulkan()
|
|||||||
createSyncObjects(); // 创建同步对象
|
createSyncObjects(); // 创建同步对象
|
||||||
_lastDrawFrameTime = getCurrentTimeMillis();
|
_lastDrawFrameTime = getCurrentTimeMillis();
|
||||||
_applicationInited = true;
|
_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;
|
||||||
}
|
}
|
||||||
|
else if (!_sceondInited) {
|
||||||
if (!_sceondInited) {
|
|
||||||
createSurface();
|
createSurface();
|
||||||
createSwapChain();
|
createSwapChain();
|
||||||
createImageViews();
|
createImageViews();
|
||||||
@@ -155,8 +158,14 @@ void Application::cleanupForWindowLost()
|
|||||||
(int)_applicationInited, (int)_sceondInited);
|
(int)_applicationInited, (int)_sceondInited);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FACE_DBG_LOG("cleanupForWindowLost: begin (imageCount=%zu MAX_FRAMES_IN_FLIGHT=%d)",
|
FACE_DBG_LOG("cleanupForWindowLost: begin (imageCount=%zu MAX_FRAMES_IN_FLIGHT=%d extent=%ux%u format=%d)",
|
||||||
swapChainImages.size(), MAX_FRAMES_IN_FLIGHT);
|
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
|
// 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
|
// to destroy. Anything weaker than this risks hitting VK_ERROR_DEVICE_LOST
|
||||||
@@ -222,29 +231,73 @@ void Application::cleanupForWindowLost()
|
|||||||
FACE_DBG_LOG("cleanupForWindowLost: done");
|
FACE_DBG_LOG("cleanupForWindowLost: done");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::reinitForNewWindow()
|
bool Application::reinitForNewWindow()
|
||||||
{
|
{
|
||||||
if (!_applicationInited) {
|
if (!_applicationInited) {
|
||||||
FACE_DBG_LOG("reinitForNewWindow: skip, _applicationInited=0 (must go through initVulkan first)");
|
FACE_DBG_LOG("reinitForNewWindow: skip, _applicationInited=0 (must go through initVulkan first)");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (_sceondInited) {
|
if (_sceondInited) {
|
||||||
FACE_DBG_LOG("reinitForNewWindow: skip, already _sceondInited=1");
|
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();
|
createSurface();
|
||||||
createSwapChain();
|
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();
|
createImageViews();
|
||||||
createFramebuffers();
|
createFramebuffers();
|
||||||
createCommandBuffer();
|
createCommandBuffer();
|
||||||
createSyncObjects();
|
createSyncObjects();
|
||||||
|
|
||||||
_sceondInited = true;
|
_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,
|
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.
|
// Rebuild the window-dependent Vulkan objects torn down above.
|
||||||
// Safe to call only after cleanupForWindowLost().
|
// 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:
|
protected:
|
||||||
void loadTexture(std::string path, Texture& tex, bool srgb, VkCommandPool pool);
|
void loadTexture(std::string path, Texture& tex, bool srgb, VkCommandPool pool);
|
||||||
|
|||||||
+34
-3
@@ -9,8 +9,10 @@
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include "../app/src/main/cpp/DebugLog.h"
|
#include "../app/src/main/cpp/DebugLog.h"
|
||||||
#define FACE_DBG_LOG(...) DebugLog::log(__VA_ARGS__)
|
#define FACE_DBG_LOG(...) DebugLog::log(__VA_ARGS__)
|
||||||
|
#define FACE_DBG_LOG_THROTTLED(key, ...) DebugLog::log_throttled(key, __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define FACE_DBG_LOG(...) ((void)0)
|
#define FACE_DBG_LOG(...) ((void)0)
|
||||||
|
#define FACE_DBG_LOG_THROTTLED(key, ...) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -906,12 +908,18 @@ void FaceApp::onWindowInit()
|
|||||||
} else {
|
} else {
|
||||||
// Recovery path after an earlier onWindowLost. Rebuild only the
|
// Recovery path after an earlier onWindowLost. Rebuild only the
|
||||||
// window-dependent Vulkan objects; keep renderPass / pipelines /
|
// 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_point(mtx_point);
|
||||||
std::unique_lock<std::mutex> lk_motion(changeMotionMtx);
|
std::unique_lock<std::mutex> lk_motion(changeMotionMtx);
|
||||||
std::unique_lock<std::mutex> lk_tex(createTextureMtx);
|
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) {
|
if (!_secondfaceAppInited) {
|
||||||
_secondfaceAppInited = true;
|
_secondfaceAppInited = true;
|
||||||
@@ -925,6 +933,29 @@ void FaceApp::onWindowInit()
|
|||||||
(int)_secondfaceAppInited, (int)_running);
|
(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()
|
void FaceApp::update_uniform_buffers()
|
||||||
{
|
{
|
||||||
uint32_t width = 480;
|
uint32_t width = 480;
|
||||||
@@ -1637,7 +1668,7 @@ Motion FaceApp::getMotionByName(string name)
|
|||||||
|
|
||||||
void FaceApp::changeMotionList(vector<string> motions, AnimationFinishedCallback callback, bool loop)
|
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",
|
"FaceApp::changeMotionList called count=%zu loop=%d _isLoadMotion=%d",
|
||||||
motions.size(), (int)loop, (int)_isLoadMotion);
|
motions.size(), (int)loop, (int)_isLoadMotion);
|
||||||
if (_isLoadMotion)
|
if (_isLoadMotion)
|
||||||
|
|||||||
+10
-1
@@ -191,8 +191,17 @@ public:
|
|||||||
|
|
||||||
// Called from main thread in response to APP_CMD_INIT_WINDOW.
|
// Called from main thread in response to APP_CMD_INIT_WINDOW.
|
||||||
// Does the full first-time initVulkan() on the very first call, and a
|
// 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();
|
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();
|
void loadMotionThread();
|
||||||
std::thread worker_;
|
std::thread worker_;
|
||||||
bool _isLoadMotion = false;
|
bool _isLoadMotion = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user