UE4在移动端上创建和销毁渲染线程
在UE4中,渲染线程会通过全局函数StartRenderingThread来创建渲染线程(渲染线程的TickHeartbeat线程,RHI线程),通过全局函数StopRenderingThread来销毁渲染线程(渲染线程的TickHeartbeat线程,RHI线程)。
/* UnrealEngine\Engine\Source\Runtime\RenderCore\Public\RenderingThread.h */ /** Starts the rendering thread. */ extern RENDERCORE_API void StartRenderingThread(); /** Stops the rendering thread. */ extern RENDERCORE_API void StopRenderingThread();
具体实现:
/* UnrealEngine\Engine\Source\Runtime\RenderCore\Private\RenderingThread.cpp */ void StartRenderingThread() { static uint32 ThreadCount = 0; check(!GIsThreadedRendering && GUseThreadedRendering); check(!IsRHIThreadRunning() && !GIsRunningRHIInSeparateThread_InternalUseOnly && !GIsRunningRHIInDedicatedThread_InternalUseOnly && !GIsRunningRHIInTaskThread_InternalUseOnly); // Pause asset streaming to prevent rendercommands from being enqueued. SuspendTextureStreamingRenderTasks(); // Flush GT since render commands issued by threads other than GT are sent to // the main queue of GT when RT is disabled. Without this flush, those commands // will run on GT after RT is enabled FlushRenderingCommands(); if (GUseRHIThread_InternalUseOnly) { FRHICommandListExecutor::GetImmediateCommandList().ImmediateFlush(EImmediateFlushType::DispatchToRHIThread); if (!FTaskGraphInterface::Get().IsThreadProcessingTasks(ENamedThreads::RHIThread)) { FRHIThread::Get().Start(); } DECLARE_CYCLE_STAT(TEXT("Wait For RHIThread"), STAT_WaitForRHIThread, STATGROUP_TaskGraphTasks); FGraphEventRef CompletionEvent = TGraphTask<FOwnershipOfRHIThreadTask>::CreateTask(NULL, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(true, GET_STATID(STAT_WaitForRHIThread)); QUICK_SCOPE_CYCLE_COUNTER(STAT_StartRenderingThread); FTaskGraphInterface::Get().WaitUntilTaskCompletes(CompletionEvent, ENamedThreads::GameThread_Local); PRAGMA_DISABLE_DEPRECATION_WARNINGS GRHIThread_InternalUseOnly = FRHIThread::Get().Thread; GRHIThreadId = GRHIThread_InternalUseOnly->GetThreadID(); PRAGMA_ENABLE_DEPRECATION_WARNINGS GIsRunningRHIInDedicatedThread_InternalUseOnly = true; GIsRunningRHIInSeparateThread_InternalUseOnly = true; GRHICommandList.LatchBypass(); } else if (GUseRHITaskThreads_InternalUseOnly) { GIsRunningRHIInSeparateThread_InternalUseOnly = true; GIsRunningRHIInTaskThread_InternalUseOnly = true; } // Turn on the threaded rendering flag. GIsThreadedRendering = true; // Create the rendering thread. GRenderingThreadRunnable = new FRenderingThread(); Trace::ThreadGroupBegin(TEXT("Render")); PRAGMA_DISABLE_DEPRECATION_WARNINGS GRenderingThread = PRAGMA_ENABLE_DEPRECATION_WARNINGS FRunnableThread::Create(GRenderingThreadRunnable, *BuildRenderingThreadName(ThreadCount), 0, FPlatformAffinity::GetRenderingThreadPriority(), FPlatformAffinity::GetRenderingThreadMask(), FPlatformAffinity::GetRenderingThreadFlags()); Trace::ThreadGroupEnd(); // Wait for render thread to have taskgraph bound before we dispatch any tasks for it. ((FRenderingThread*)GRenderingThreadRunnable)->TaskGraphBoundSyncEvent->Wait(); // register IConsoleManager::Get().RegisterThreadPropagation(0, &FConsoleRenderThreadPropagation::GetSingleton()); // ensure the thread has actually started and is idling FRenderCommandFence Fence; Fence.BeginFence(); Fence.Wait(); GRunRenderingThreadHeartbeat = true; // Create the rendering thread heartbeat GRenderingThreadRunnableHeartbeat = new FRenderingThreadTickHeartbeat(); Trace::ThreadGroupBegin(TEXT("Render")); GRenderingThreadHeartbeat = FRunnableThread::Create(GRenderingThreadRunnableHeartbeat, *FString::Printf(TEXT("RTHeartBeat %d"), ThreadCount), 16 * 1024, TPri_AboveNormal, FPlatformAffinity::GetRTHeartBeatMask()); Trace::ThreadGroupEnd(); ThreadCount++; // Update can now resume. ResumeTextureStreamingRenderTasks(); } void StopRenderingThread() { // This function is not thread-safe. Ensure it is only called by the main game thread. check( IsInGameThread() ); // unregister IConsoleManager::Get().RegisterThreadPropagation(); // stop the render thread heartbeat first if (GRunRenderingThreadHeartbeat) { GRunRenderingThreadHeartbeat = false; // Wait for the rendering thread heartbeat to return. GRenderingThreadHeartbeat->WaitForCompletion(); delete GRenderingThreadHeartbeat; GRenderingThreadHeartbeat = NULL; delete GRenderingThreadRunnableHeartbeat; GRenderingThreadRunnableHeartbeat = NULL; } if( GIsThreadedRendering ) { // Get the list of objects which need to be cleaned up when the rendering thread is done with them. FPendingCleanupObjects* PendingCleanupObjects = GetPendingCleanupObjects(); // Make sure we're not in the middle of streaming textures. SuspendTextureStreamingRenderTasks(); // Wait for the rendering thread to finish executing all enqueued commands. FlushRenderingCommands(); // The rendering thread may have already been stopped during the call to GFlushStreamingFunc or FlushRenderingCommands. if ( GIsThreadedRendering ) { if (IsRHIThreadRunning()) { DECLARE_CYCLE_STAT(TEXT("Wait For RHIThread Finish"), STAT_WaitForRHIThreadFinish, STATGROUP_TaskGraphTasks); FGraphEventRef ReleaseTask = TGraphTask<FOwnershipOfRHIThreadTask>::CreateTask(NULL, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(false, GET_STATID(STAT_WaitForRHIThreadFinish)); QUICK_SCOPE_CYCLE_COUNTER(STAT_StopRenderingThread_RHIThread); FTaskGraphInterface::Get().WaitUntilTaskCompletes(ReleaseTask, ENamedThreads::GameThread_Local); PRAGMA_DISABLE_DEPRECATION_WARNINGS GRHIThread_InternalUseOnly = nullptr; GRHIThreadId = 0; PRAGMA_ENABLE_DEPRECATION_WARNINGS } GIsRunningRHIInSeparateThread_InternalUseOnly = false; GIsRunningRHIInDedicatedThread_InternalUseOnly = false; GIsRunningRHIInTaskThread_InternalUseOnly = false; check(!GIsRenderingThreadSuspended.Load(EMemoryOrder::Relaxed)); // Turn off the threaded rendering flag. GIsThreadedRendering = false; { FGraphEventRef QuitTask = TGraphTask<FReturnGraphTask>::CreateTask(NULL, ENamedThreads::GameThread).ConstructAndDispatchWhenReady(ENamedThreads::GetRenderThread()); // Busy wait while BP debugging, to avoid opportunistic execution of game thread tasks // If the game thread is already executing tasks, then we have no choice but to spin if (GIntraFrameDebuggingGameThread || FTaskGraphInterface::Get().IsThreadProcessingTasks(ENamedThreads::GameThread) ) { while ((QuitTask.GetReference() != nullptr) && !QuitTask->IsComplete()) { FPlatformProcess::Sleep(0.0f); } } else { QUICK_SCOPE_CYCLE_COUNTER(STAT_StopRenderingThread); FTaskGraphInterface::Get().WaitUntilTaskCompletes(QuitTask, ENamedThreads::GameThread_Local); } } // Wait for the rendering thread to return. PRAGMA_DISABLE_DEPRECATION_WARNINGS GRenderingThread->WaitForCompletion(); // Destroy the rendering thread objects. delete GRenderingThread; GRenderingThread = NULL; PRAGMA_ENABLE_DEPRECATION_WARNINGS GRHICommandList.LatchBypass(); delete GRenderingThreadRunnable; GRenderingThreadRunnable = NULL; } // Delete the pending cleanup objects which were in use by the rendering thread. delete PendingCleanupObjects; // Update can now resume with renderthread being the gamethread. ResumeTextureStreamingRenderTasks(); } check(!IsRHIThreadRunning()); }
FSuspendRenderingThread
为了方面使用还封装了一个FSuspendRenderingThread类,使用RAII机制在其构造函数中调用StopRenderingThread销毁渲染线程,离开作用域后,在其析构函数中调用StartRenderingThread再创建出渲染线程(同一帧)。
/* UnrealEngine\Engine\Source\Runtime\RenderCore\Private\RenderingThread.cpp */ /** * Constructor that flushes and suspends the renderthread * @param bRecreateThread - Whether the rendering thread should be completely destroyed and recreated, or just suspended. */ FSuspendRenderingThread::FSuspendRenderingThread( bool bInRecreateThread ) { // Suspend async loading thread so that it doesn't start queueing render commands // while the render thread is suspended. if (IsAsyncLoadingMultithreaded()) { SuspendAsyncLoading(); } // Pause asset streaming to prevent rendercommands from being enqueued. SuspendTextureStreamingRenderTasks(); bRecreateThread = bInRecreateThread; bUseRenderingThread = GUseThreadedRendering; bWasRenderingThreadRunning = GIsThreadedRendering; if ( bRecreateThread ) { StopRenderingThread(); // GUseThreadedRendering should be set to false after StopRenderingThread call since // otherwise a wrong context could be used. GUseThreadedRendering = false; ++GIsRenderingThreadSuspended; } else { if ( GIsRenderingThreadSuspended.Load(EMemoryOrder::Relaxed) == 0 ) { // First tell the render thread to finish up all pending commands and then suspend its activities. // this ensures that async stuff will be completed too FlushRenderingCommands(); if (GIsThreadedRendering) { DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.SuspendRendering"), STAT_FSimpleDelegateGraphTask_SuspendRendering, STATGROUP_TaskGraphTasks); ENamedThreads::Type RenderThread = ENamedThreads::GetRenderThread(); FGraphEventRef CompleteHandle = FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateStatic(&SuspendRendering), GET_STATID(STAT_FSimpleDelegateGraphTask_SuspendRendering), NULL, RenderThread); // Busy wait while Kismet debugging, to avoid opportunistic execution of game thread tasks // If the game thread is already executing tasks, then we have no choice but to spin if (GIntraFrameDebuggingGameThread || FTaskGraphInterface::Get().IsThreadProcessingTasks(ENamedThreads::GameThread) ) { while (!GIsRenderingThreadSuspended.Load(EMemoryOrder::Relaxed)) { FPlatformProcess::Sleep(0.0f); } } else { QUICK_SCOPE_CYCLE_COUNTER(STAT_FSuspendRenderingThread); FTaskGraphInterface::Get().WaitUntilTaskCompletes(CompleteHandle, ENamedThreads::GameThread); } check(GIsRenderingThreadSuspended.Load(EMemoryOrder::Relaxed)); // Now tell the render thread to busy wait until it's resumed DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.WaitAndResumeRendering"), STAT_FSimpleDelegateGraphTask_WaitAndResumeRendering, STATGROUP_TaskGraphTasks); FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateStatic(&WaitAndResumeRendering), GET_STATID(STAT_FSimpleDelegateGraphTask_WaitAndResumeRendering), NULL, RenderThread); } else { SuspendRendering(); } } else { // The render-thread is already suspended. Just bump the ref-count. ++GIsRenderingThreadSuspended; } } } /** Destructor that starts the renderthread again */ FSuspendRenderingThread::~FSuspendRenderingThread() { if ( bRecreateThread ) { GUseThreadedRendering = bUseRenderingThread; --GIsRenderingThreadSuspended; if ( bUseRenderingThread && bWasRenderingThreadRunning ) { StartRenderingThread(); // Now tell the render thread to set it self to real time mode DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.SetRealTimeMode"), STAT_FSimpleDelegateGraphTask_SetRealTimeMode, STATGROUP_TaskGraphTasks); FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateStatic(&FPlatformProcess::SetRealTimeMode), GET_STATID(STAT_FSimpleDelegateGraphTask_SetRealTimeMode), NULL, ENamedThreads::GetRenderThread() ); } } else { // Resume the render thread again. --GIsRenderingThreadSuspended; } // Resume any asset streaming ResumeTextureStreamingRenderTasks(); if (IsAsyncLoadingMultithreaded()) { ResumeAsyncLoading(); } }
SCOPED_SUSPEND_RENDERING_THREAD
为了进一步方便使用,引擎还提供了一个宏来定义一个FSuspendRenderingThread SuspendRenderingThread(bRecreateThread)对象。
/* UnrealEngine\Engine\Source\Runtime\RenderCore\Public\RenderingThread.h */ /** Helper macro for safely flushing and suspending the rendering thread while manipulating graphics resources */ #define SCOPED_SUSPEND_RENDERING_THREAD(bRecreateThread) FSuspendRenderingThread SuspendRenderingThread(bRecreateThread)
引擎初始化时,创建渲染线程
直接调用全局函数StartRenderingThread来创建渲染线程
Android堆栈:
> libUE4.so!StartRenderingThread() Line 734 c++ libUE4.so!FEngineLoop::PreInitPreStartupScreen(FEngineLoop * this = 0x00000072a3166bc0, const TCHAR * CmdLine = 0x000000734cd907a0) Line 2713 c++ libUE4.so!FEngineLoop::PreInit(FEngineLoop * this = 0x00000072a3166bc0, const TCHAR * CmdLine = 0x000000734cd907a0) Line 3625 c++ libUE4.so!FEngineLoop::PreInit(FEngineLoop * this = 0x00000072a3166bc0, int32 ArgC = 0, TCHAR ** ArgV = 0x0000000000000000, const TCHAR * AdditionalCommandline = 0x00000072a355a302) Line 1242 c++ libUE4.so!AndroidMain(android_app * state = 0x000000734cc7dd80) Line 524 c++ libUE4.so!android_main(android_app * state = 0x000000734cc7dd80) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x000000734cc7dd80) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown
iOS堆栈:
* frame #0: 0x000000010b3098d0 MyGame`StartRenderingThread() at RenderingThread.cpp:735:2 frame #1: 0x0000000104b12364 MyGame`FEngineLoop::PreInitPreStartupScreen(this=0x0000000112c51400, CmdLine=L" ") at LaunchEngineLoop.cpp:2714:4 frame #2: 0x0000000104b06ff8 MyGame`FEngineLoop::PreInit(this=0x0000000112c51400, CmdLine=L" ") at LaunchEngineLoop.cpp:3626:20 frame #3: 0x0000000104b06c70 MyGame`FAppEntry::Init() at LaunchIOS.cpp:410:14 frame #4: 0x000000010a7df258 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:440:2 frame #5: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #6: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148
播放完启动视频后,销毁并重新创建渲染线程
通过SCOPED_SUSPEND_RENDERING_THREAD(true)的RAII机制来实现
Android堆栈:
// 销毁渲染线程 > libUE4.so!StopRenderingThread() Line 812 c++ libUE4.so!FSuspendRenderingThread::FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072f9192790, bool bInRecreateThread = true) Line 124 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x000000723f931910, bool bDestroyed = false, uint32 NewSizeX = 2336, uint32 NewSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1647 c++ libUE4.so!FSceneViewport::ResizeViewport(FSceneViewport * this = 0x000000723f931910, uint32 NewSizeX = 2336, uint32 NewSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen) Line 1545 c++ libUE4.so!FSceneViewport::ResizeFrame(FSceneViewport * this = 0x000000723f931910, uint32 NewWindowSizeX = 2336, uint32 NewWindowSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen) Line 1448 c++ libUE4.so!UGameEngine::SwitchGameWindowToUseGameViewport(UMyGameEngine * this = 0x000000734d03b010) Line 674 c++ libUE4.so!FDefaultGameMoviePlayer::WaitForMovieToFinish(FDefaultGameMoviePlayer * this = 0x0000007210bcae10, bool bAllowEngineTick = true) Line 610 c++ libUE4.so!non-virtual thunk to FDefaultGameMoviePlayer::WaitForMovieToFinish(FDefaultGameMoviePlayer * this = 0x0000007210bcae10, bool bAllowEngineTick = true) c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072a3166bc0) Line 4933 c++ libUE4.so!AndroidMain(android_app * state = 0x000000734cc7dd80) Line 581 c++ libUE4.so!android_main(android_app * state = 0x000000734cc7dd80) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x000000734cc7dd80) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown // 创建渲染线程 > libUE4.so!StartRenderingThread() Line 734 c++ libUE4.so!FSuspendRenderingThread::~FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072f9192790) Line 197 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x000000723f931910, bool bDestroyed = false, uint32 NewSizeX = 2336, uint32 NewSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1697 c++ libUE4.so!FSceneViewport::ResizeViewport(FSceneViewport * this = 0x000000723f931910, uint32 NewSizeX = 2336, uint32 NewSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen) Line 1545 c++ libUE4.so!FSceneViewport::ResizeFrame(FSceneViewport * this = 0x000000723f931910, uint32 NewWindowSizeX = 2336, uint32 NewWindowSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen) Line 1448 c++ libUE4.so!UGameEngine::SwitchGameWindowToUseGameViewport(UMyGameEngine * this = 0x000000734d03b010) Line 674 c++ libUE4.so!FDefaultGameMoviePlayer::WaitForMovieToFinish(FDefaultGameMoviePlayer * this = 0x0000007210bcae10, bool bAllowEngineTick = true) Line 610 c++ libUE4.so!non-virtual thunk to FDefaultGameMoviePlayer::WaitForMovieToFinish(FDefaultGameMoviePlayer * this = 0x0000007210bcae10, bool bAllowEngineTick = true) c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072a3166bc0) Line 4933 c++ libUE4.so!AndroidMain(android_app * state = 0x000000734cc7dd80) Line 581 c++ libUE4.so!android_main(android_app * state = 0x000000734cc7dd80) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x000000734cc7dd80) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown
iOS堆栈:
// 销毁渲染线程 * frame #0: 0x000000010b308d7c MyGame`StopRenderingThread() at RenderingThread.cpp:813:2 frame #1: 0x000000010b308a9c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x0000000170345c21, bInRecreateThread=true) at RenderingThread.cpp:125:3 frame #2: 0x000000010b30968c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x0000000170345c21, bInRecreateThread=true) at RenderingThread.cpp:109:1 frame #3: 0x000000010e41ea68 MyGame`FSceneViewport::UpdateViewportRHI(this=0x0000000164977730, bDestroyed=false, NewSizeX=2778, NewSizeY=1284, NewWindowMode=Fullscreen, PreferredPixelFormat=PF_Unknown) at SceneViewport.cpp:1648:3 frame #4: 0x000000010e41e2a8 MyGame`FSceneViewport::ResizeViewport(this=0x0000000164977730, NewSizeX=2778, NewSizeY=1284, NewWindowMode=Fullscreen) at SceneViewport.cpp:1546:3 frame #5: 0x000000010e41de40 MyGame`FSceneViewport::ResizeFrame(this=0x0000000164977730, NewWindowSizeX=2778, NewWindowSizeY=1284, NewWindowMode=Fullscreen) at SceneViewport.cpp:1449:5 frame #6: 0x000000010da22870 MyGame`UGameEngine::SwitchGameWindowToUseGameViewport(this=0x0000000144e70200) at GameEngine.cpp:675:19 frame #7: 0x000000010d1978dc MyGame`FDefaultGameMoviePlayer::WaitForMovieToFinish(this=0x000000015b25dd60, bAllowEngineTick=true) at DefaultGameMoviePlayer.cpp:611:16 frame #8: 0x0000000104b09680 MyGame`FEngineLoop::Tick(this=0x0000000112c51400) at LaunchEngineLoop.cpp:4934:23 frame #9: 0x0000000104b08624 MyGame`FAppEntry::Tick() at LaunchIOS.cpp:523:14 frame #10: 0x000000010a7df8d4 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:562:13 frame #11: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #12: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148 // 创建渲染线程 * frame #0: 0x000000010b3098d0 MyGame`StartRenderingThread() at RenderingThread.cpp:735:2 frame #1: 0x000000010b309710 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x0000000170345c21) at RenderingThread.cpp:198:4 frame #2: 0x000000010b309e40 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x0000000170345c21) at RenderingThread.cpp:191:1 frame #3: 0x000000010e41ec18 MyGame`FSceneViewport::UpdateViewportRHI(this=0x0000000164977730, bDestroyed=false, NewSizeX=2778, NewSizeY=1284, NewWindowMode=Fullscreen, PreferredPixelFormat=PF_Unknown) at SceneViewport.cpp:1698:2 frame #4: 0x000000010e41e2a8 MyGame`FSceneViewport::ResizeViewport(this=0x0000000164977730, NewSizeX=2778, NewSizeY=1284, NewWindowMode=Fullscreen) at SceneViewport.cpp:1546:3 frame #5: 0x000000010e41de40 MyGame`FSceneViewport::ResizeFrame(this=0x0000000164977730, NewWindowSizeX=2778, NewWindowSizeY=1284, NewWindowMode=Fullscreen) at SceneViewport.cpp:1449:5 frame #6: 0x000000010da22870 MyGame`UGameEngine::SwitchGameWindowToUseGameViewport(this=0x0000000144e70200) at GameEngine.cpp:675:19 frame #7: 0x000000010d1978dc MyGame`FDefaultGameMoviePlayer::WaitForMovieToFinish(this=0x000000015b25dd60, bAllowEngineTick=true) at DefaultGameMoviePlayer.cpp:611:16 frame #8: 0x0000000104b09680 MyGame`FEngineLoop::Tick(this=0x0000000112c51400) at LaunchEngineLoop.cpp:4934:23 frame #9: 0x0000000104b08624 MyGame`FAppEntry::Tick() at LaunchIOS.cpp:523:14 frame #10: 0x000000010a7df8d4 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:562:13 frame #11: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #12: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148
LoadMap进入没有LoadingScreen的地图,同一帧连续2次销毁并重新创建渲染线程
都是通过SCOPED_SUSPEND_RENDERING_THREAD(true)的RAII机制来实现
① 在FStreamingPauseRenderingModule::BeginStreamingPause中通过GetMoviePlayer()->IsMovieCurrentlyPlaying()来判断是不是没有LoadingScreen,没有则调用FSceneViewport::UpdateViewportRHI来销毁并重新创建渲染线程
Android堆栈:
// 销毁渲染线程 > libUE4.so!StopRenderingThread() Line 812 c++ libUE4.so!FSuspendRenderingThread::FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072f9190300, bool bInRecreateThread = true) Line 124 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x00000072080b2210, bool bDestroyed = false, uint32 NewSizeX = 2336, uint32 NewSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1647 c++ libUE4.so!FStreamingPauseRenderingModule::BeginStreamingPause(FStreamingPauseRenderingModule * this = 0x000000734d041e10, FSceneViewport * GameViewport = 0x000000723f931910) Line 128 c++ libUE4.so!decltype(UE4Invoke_Private::DereferenceIfNecessary<FStreamingPauseRenderingModule>(Forward<FStreamingPauseRenderingModule*&>(fp0)).*fp(Forward<FViewport*&>(fp1))) Invoke<void, FStreamingPauseRenderingModule, FViewport*, FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::*)(FViewport *) PtrMemFun = 50 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, FStreamingPauseRenderingModule *& Callable = 0x00000072f9190e78, FViewport *& Args = 0x00000072f9190e80) Line 64 c++ libUE4.so!decltype(auto) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&) const(const UE4Tuple_Private::TTupleBase<TIntegerSequence<> > * this = 0x0000007209c1f1b8, void (FStreamingPauseRenderingModule::*const &)(FViewport *) Func = 0x0000007209c1f1d0, FStreamingPauseRenderingModule *& Args = 0x00000072f9190e78, FViewport *& Args = 0x00000072f9190e80) Line 298 c++ libUE4.so!TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (FViewport*), FDefaultDelegateUserPolicy>::Execute(FViewport*) const(const TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (FViewport *), FDefaultDelegateUserPolicy> * this = 0x0000007209c1f1b0, FSceneViewport * Params = 0x000000723f931910) Line 451 c++ libUE4.so!TDelegate<void (FViewport*), FDefaultDelegateUserPolicy>::Execute(FViewport*) const(const TDelegate<void (FViewport *), FDefaultDelegateUserPolicy> * this = 0x000000734d041e48, FSceneViewport * Params = 0x000000723f931910) Line 579 c++ libUE4.so!UEngine::BlockTillLevelStreamingCompleted(UMyGameEngine * this = 0x000000734d03b010, UWorld * InWorld = 0x0000007209c0b210) Line 13816 c++ libUE4.so!AGameMode::HandleMatchHasStarted(AGameMode * this = 0x0000007240616a10) Line 236 c++ libUE4.so!AGameMode::OnMatchStateSet(AGameMode * this = 0x0000007240616a10) Line 386 c++ libUE4.so!AGameMode::SetMatchState(AGameMode * this = 0x0000007240616a10, FName NewState = ) Line 365 c++ libUE4.so!AGameMode::StartMatch(AGameMode * this = 0x0000007240616a10) Line 214 c++ libUE4.so!AGameMode::StartPlay(AGameMode * this = 0x0000007240616a10) Line 158 c++ libUE4.so!UWorld::BeginPlay(UWorld * this = 0x0000007209c0b210) Line 4602 c++ libUE4.so!UEngine::LoadMap(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , UPendingNetGame * Pending = 0x0000000000000000, FString & Error = 0x00000072f9192888) Line 13729 c++ libUE4.so!UEngine::Browse(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , FString & Error = 0x00000072f9192888) Line 12891 c++ libUE4.so!UEngine::TickWorldTravel(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & Context = 0x00000072085f6210, float DeltaSeconds = 20.7358685) Line 13089 c++ libUE4.so!UGameEngine::Tick(UMyGameEngine * this = 0x000000734d03b010, float DeltaSeconds = 20.7358685, bool bIdleMode = false) Line 1836 c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072a3166bc0) Line 4903 c++ libUE4.so!AndroidMain(android_app * state = 0x000000734cc7dd80) Line 581 c++ libUE4.so!android_main(android_app * state = 0x000000734cc7dd80) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x000000734cc7dd80) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown // 创建渲染线程 > libUE4.so!StartRenderingThread() Line 734 c++ libUE4.so!FSuspendRenderingThread::~FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072f9190300) Line 197 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x00000072080b2210, bool bDestroyed = false, uint32 NewSizeX = 2336, uint32 NewSizeY = 1080, EWindowMode::Type NewWindowMode = Fullscreen, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1697 c++ libUE4.so!FStreamingPauseRenderingModule::BeginStreamingPause(FStreamingPauseRenderingModule * this = 0x000000734d041e10, FSceneViewport * GameViewport = 0x000000723f931910) Line 128 c++ libUE4.so!decltype(UE4Invoke_Private::DereferenceIfNecessary<FStreamingPauseRenderingModule>(Forward<FStreamingPauseRenderingModule*&>(fp0)).*fp(Forward<FViewport*&>(fp1))) Invoke<void, FStreamingPauseRenderingModule, FViewport*, FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::*)(FViewport *) PtrMemFun = 50 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, FStreamingPauseRenderingModule *& Callable = 0x00000072f9190e78, FViewport *& Args = 0x00000072f9190e80) Line 64 c++ libUE4.so!decltype(auto) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&) const(const UE4Tuple_Private::TTupleBase<TIntegerSequence<> > * this = 0x0000007209c1f1b8, void (FStreamingPauseRenderingModule::*const &)(FViewport *) Func = 0x0000007209c1f1d0, FStreamingPauseRenderingModule *& Args = 0x00000072f9190e78, FViewport *& Args = 0x00000072f9190e80) Line 298 c++ libUE4.so!TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (FViewport*), FDefaultDelegateUserPolicy>::Execute(FViewport*) const(const TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (FViewport *), FDefaultDelegateUserPolicy> * this = 0x0000007209c1f1b0, FSceneViewport * Params = 0x000000723f931910) Line 451 c++ libUE4.so!TDelegate<void (FViewport*), FDefaultDelegateUserPolicy>::Execute(FViewport*) const(const TDelegate<void (FViewport *), FDefaultDelegateUserPolicy> * this = 0x000000734d041e48, FSceneViewport * Params = 0x000000723f931910) Line 579 c++ libUE4.so!UEngine::BlockTillLevelStreamingCompleted(UMyGameEngine * this = 0x000000734d03b010, UWorld * InWorld = 0x0000007209c0b210) Line 13816 c++ libUE4.so!AGameMode::HandleMatchHasStarted(AGameMode * this = 0x0000007240616a10) Line 236 c++ libUE4.so!AGameMode::OnMatchStateSet(AGameMode * this = 0x0000007240616a10) Line 386 c++ libUE4.so!AGameMode::SetMatchState(AGameMode * this = 0x0000007240616a10, FName NewState = ) Line 365 c++ libUE4.so!AGameMode::StartMatch(AGameMode * this = 0x0000007240616a10) Line 214 c++ libUE4.so!AGameMode::StartPlay(AGameMode * this = 0x0000007240616a10) Line 158 c++ libUE4.so!UWorld::BeginPlay(UWorld * this = 0x0000007209c0b210) Line 4602 c++ libUE4.so!UEngine::LoadMap(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , UPendingNetGame * Pending = 0x0000000000000000, FString & Error = 0x00000072f9192888) Line 13729 c++ libUE4.so!UEngine::Browse(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , FString & Error = 0x00000072f9192888) Line 12891 c++ libUE4.so!UEngine::TickWorldTravel(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & Context = 0x00000072085f6210, float DeltaSeconds = 20.7358685) Line 13089 c++ libUE4.so!UGameEngine::Tick(UMyGameEngine * this = 0x000000734d03b010, float DeltaSeconds = 20.7358685, bool bIdleMode = false) Line 1836 c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072a3166bc0) Line 4903 c++ libUE4.so!AndroidMain(android_app * state = 0x000000734cc7dd80) Line 581 c++ libUE4.so!android_main(android_app * state = 0x000000734cc7dd80) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x000000734cc7dd80) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown
iOS堆栈:
// 销毁渲染线程 * frame #0: 0x000000010b308d7c MyGame`StopRenderingThread() at RenderingThread.cpp:813:2 frame #1: 0x000000010b308a9c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x0000000170343b91, bInRecreateThread=true) at RenderingThread.cpp:125:3 frame #2: 0x000000010b30968c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x0000000170343b91, bInRecreateThread=true) at RenderingThread.cpp:109:1 frame #3: 0x000000010e41ea68 MyGame`FSceneViewport::UpdateViewportRHI(this=0x00000002d1d90180, bDestroyed=false, NewSizeX=2778, NewSizeY=1284, NewWindowMode=Fullscreen, PreferredPixelFormat=PF_Unknown) at SceneViewport.cpp:1648:3 frame #4: 0x000000010d1ab154 MyGame`FStreamingPauseRenderingModule::BeginStreamingPause(this=0x00000002811d1620, GameViewport=0x0000000164977738) at StreamingPauseRendering.cpp:129:19 frame #5: 0x000000010d1ad080 MyGame`decltype(PtrMemFun=50 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, Callable=0x0000000170344688, Args=0x0000000170344690)).*fp(Forward<FViewport*&>(fp1))) Invoke<void, FStreamingPauseRenderingModule, FViewport*, FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::*)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&) at Invoke.h:65:9 frame #6: 0x000000010d1acfd8 MyGame`decltype(this=0x0000000282886e88, Func=0x0000000282886ea0, Args=0x0000000170344688, Args=0x0000000170344690) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int> >::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&) const at Tuple.h:299:11 frame #7: 0x000000010d1acc58 MyGame`TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (FViewport*), FDefaultDelegateUserPolicy>::Execute(this=0x0000000282886e80, Params=0x0000000164977738) const at DelegateInstancesImpl.h:452:24 frame #8: 0x000000010d294164 MyGame`TDelegate<void (FViewport*), FDefaultDelegateUserPolicy>::Execute(this=0x00000002811d1658, Params=0x0000000164977738) const at DelegateSignatureImpl.inl:580:33 frame #9: 0x000000010d293f50 MyGame`UEngine::BlockTillLevelStreamingCompleted(this=0x0000000144e70200, InWorld=0x0000000144c49600) at UnrealEngine.cpp:13817:42 frame #10: 0x000000010da6ba08 MyGame`AGameMode::HandleMatchHasStarted(this=0x000000016e126a00) at GameMode.cpp:237:12 frame #11: 0x000000010da6c694 MyGame`AGameMode::OnMatchStateSet(this=0x000000016e126a00) at GameMode.cpp:387:3 frame #12: 0x000000010da6c22c MyGame`AGameMode::SetMatchState(this=0x000000016e126a00, NewState=name=b'InProgress') at GameMode.cpp:366:2 frame #13: 0x000000010da6b8f8 MyGame`AGameMode::StartMatch(this=0x000000016e126a00) at GameMode.cpp:215:2 frame #14: 0x000000010da6b734 MyGame`AGameMode::StartPlay(this=0x000000016e126a00) at GameMode.cpp:159:3 frame #15: 0x000000010e746a84 MyGame`UWorld::BeginPlay(this=0x0000000144c49600) at World.cpp:4603:13 frame #16: 0x000000010d2917b8 MyGame`UEngine::LoadMap(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x00000001703457b0, Pending=0x0000000000000000, Error=string=None) at UnrealEngine.cpp:13730:24 frame #17: 0x000000010d28db2c MyGame`UEngine::Browse(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x0000000170345ca0, Error=string=None) at UnrealEngine.cpp:12892:10 frame #18: 0x000000010d28f358 MyGame`UEngine::TickWorldTravel(this=0x0000000144e70200, Context=0x000000016635cc90, DeltaSeconds=10.3148842) at UnrealEngine.cpp:13090:7 frame #19: 0x000000010da26f20 MyGame`UGameEngine::Tick(this=0x0000000144e70200, DeltaSeconds=10.3148842, bIdleMode=false) at GameEngine.cpp:1837:4 frame #20: 0x0000000104b09578 MyGame`FEngineLoop::Tick(this=0x0000000112c51400) at LaunchEngineLoop.cpp:4904:12 frame #21: 0x0000000104b08624 MyGame`FAppEntry::Tick() at LaunchIOS.cpp:523:14 frame #22: 0x000000010a7df8d4 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:562:13 frame #23: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #24: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148 // 创建渲染线程 * frame #0: 0x000000010b3098d0 MyGame`StartRenderingThread() at RenderingThread.cpp:735:2 frame #1: 0x000000010b309710 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x0000000170343b91) at RenderingThread.cpp:198:4 frame #2: 0x000000010b309e40 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x0000000170343b91) at RenderingThread.cpp:191:1 frame #3: 0x000000010e41ec18 MyGame`FSceneViewport::UpdateViewportRHI(this=0x00000002d1d90180, bDestroyed=false, NewSizeX=2778, NewSizeY=1284, NewWindowMode=Fullscreen, PreferredPixelFormat=PF_Unknown) at SceneViewport.cpp:1698:2 frame #4: 0x000000010d1ab154 MyGame`FStreamingPauseRenderingModule::BeginStreamingPause(this=0x00000002811d1620, GameViewport=0x0000000164977738) at StreamingPauseRendering.cpp:129:19 frame #5: 0x000000010d1ad080 MyGame`decltype(PtrMemFun=50 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, Callable=0x0000000170344688, Args=0x0000000170344690)).*fp(Forward<FViewport*&>(fp1))) Invoke<void, FStreamingPauseRenderingModule, FViewport*, FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::*)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&) at Invoke.h:65:9 frame #6: 0x000000010d1acfd8 MyGame`decltype(this=0x0000000282886e88, Func=0x0000000282886ea0, Args=0x0000000170344688, Args=0x0000000170344690) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int> >::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&>(void (FStreamingPauseRenderingModule::* const&)(FViewport*), FStreamingPauseRenderingModule*&, FViewport*&) const at Tuple.h:299:11 frame #7: 0x000000010d1acc58 MyGame`TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (FViewport*), FDefaultDelegateUserPolicy>::Execute(this=0x0000000282886e80, Params=0x0000000164977738) const at DelegateInstancesImpl.h:452:24 frame #8: 0x000000010d294164 MyGame`TDelegate<void (FViewport*), FDefaultDelegateUserPolicy>::Execute(this=0x00000002811d1658, Params=0x0000000164977738) const at DelegateSignatureImpl.inl:580:33 frame #9: 0x000000010d293f50 MyGame`UEngine::BlockTillLevelStreamingCompleted(this=0x0000000144e70200, InWorld=0x0000000144c49600) at UnrealEngine.cpp:13817:42 frame #10: 0x000000010da6ba08 MyGame`AGameMode::HandleMatchHasStarted(this=0x000000016e126a00) at GameMode.cpp:237:12 frame #11: 0x000000010da6c694 MyGame`AGameMode::OnMatchStateSet(this=0x000000016e126a00) at GameMode.cpp:387:3 frame #12: 0x000000010da6c22c MyGame`AGameMode::SetMatchState(this=0x000000016e126a00, NewState=name=b'InProgress') at GameMode.cpp:366:2 frame #13: 0x000000010da6b8f8 MyGame`AGameMode::StartMatch(this=0x000000016e126a00) at GameMode.cpp:215:2 frame #14: 0x000000010da6b734 MyGame`AGameMode::StartPlay(this=0x000000016e126a00) at GameMode.cpp:159:3 frame #15: 0x000000010e746a84 MyGame`UWorld::BeginPlay(this=0x0000000144c49600) at World.cpp:4603:13 frame #16: 0x000000010d2917b8 MyGame`UEngine::LoadMap(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x00000001703457b0, Pending=0x0000000000000000, Error=string=None) at UnrealEngine.cpp:13730:24 frame #17: 0x000000010d28db2c MyGame`UEngine::Browse(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x0000000170345ca0, Error=string=None) at UnrealEngine.cpp:12892:10 frame #18: 0x000000010d28f358 MyGame`UEngine::TickWorldTravel(this=0x0000000144e70200, Context=0x000000016635cc90, DeltaSeconds=10.3148842) at UnrealEngine.cpp:13090:7 frame #19: 0x000000010da26f20 MyGame`UGameEngine::Tick(this=0x0000000144e70200, DeltaSeconds=10.3148842, bIdleMode=false) at GameEngine.cpp:1837:4 frame #20: 0x0000000104b09578 MyGame`FEngineLoop::Tick(this=0x0000000112c51400) at LaunchEngineLoop.cpp:4904:12 frame #21: 0x0000000104b08624 MyGame`FAppEntry::Tick() at LaunchIOS.cpp:523:14 frame #22: 0x000000010a7df8d4 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:562:13 frame #23: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #24: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148
② 同一帧在FStreamingPauseRenderingModule::EndStreamingPause中将TSharedPtr<FSceneViewport> SceneViewport置nullptr,再次触发销毁并重新创建渲染线程逻辑
Android堆栈:
// 销毁渲染线程 > libUE4.so!StopRenderingThread() Line 812 c++ libUE4.so!FSuspendRenderingThread::FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072f9190b80, bool bInRecreateThread = true) Line 124 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x00000072080b2210, bool bDestroyed = true, uint32 NewSizeX = 0, uint32 NewSizeY = 0, EWindowMode::Type NewWindowMode = Windowed, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1647 c++ libUE4.so!FSceneViewport::Destroy(FSceneViewport * this = 0x00000072080b2210) Line 175 c++ libUE4.so!FSceneViewport::~FSceneViewport(FSceneViewport * this = 0x00000072080b2210) Line 77 c++ libUE4.so!FSceneViewport::~FSceneViewport(FSceneViewport * this = 0x00000072080b2210) Line 76 c++ libUE4.so!SharedPointerInternals::DefaultDeleter<FSceneViewport>::operator()(FSceneViewport*) const(const SharedPointerInternals::DefaultDeleter<FSceneViewport> * this = 0x000000723f62fa50, FSceneViewport * Object = 0x00000072080b2210) Line 163 c++ libUE4.so!SharedPointerInternals::TReferenceControllerWithDeleter<FSceneViewport, SharedPointerInternals::DefaultDeleter<FSceneViewport>>::DestroyObject(SharedPointerInternals::TReferenceControllerWithDeleter<FSceneViewport, SharedPointerInternals::DefaultDeleter<FSceneViewport> > * this = 0x000000723f62fa50) Line 115 c++ libUE4.so!SharedPointerInternals::FReferenceControllerOps<(ESPMode)1>::ReleaseSharedReference(SharedPointerInternals::FReferenceControllerBase * ReferenceController = 0x000000723f62fa50) Line 281 c++ libUE4.so!SharedPointerInternals::FSharedReferencer<(ESPMode)1>::operator=(SharedPointerInternals::FSharedReferencer<ESPMode::Fast> * this = 0x000000734d041e20, SharedPointerInternals::FSharedReferencer<ESPMode::Fast> && InSharedReference = 0x00000072f9190d30) Line 515 c++ libUE4.so!TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(TSharedPtr<FSceneViewport, ESPMode::Fast> * this = 0x000000734d041e18, TSharedPtr<FSceneViewport, ESPMode::Fast> && InSharedPtr = 0x00000072f9190d28) Line 790 c++ libUE4.so!TSharedPtr<FSceneViewport, (ESPMode)1>::Reset(TSharedPtr<FSceneViewport, ESPMode::Fast> * this = 0x000000734d041e18) Line 899 c++ libUE4.so!TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(TSharedPtr<FSceneViewport, ESPMode::Fast> * this = 0x000000734d041e18, SharedPointerInternals::FNullTag * = 0x0000000000000000) Line 766 c++ libUE4.so!FStreamingPauseRenderingModule::EndStreamingPause(FStreamingPauseRenderingModule * this = 0x000000734d041e10) Line 173 c++ libUE4.so!decltype(UE4Invoke_Private::DereferenceIfNecessary<FStreamingPauseRenderingModule>(Forward<FStreamingPauseRenderingModule*&>(fp0)).*fp()) Invoke<void, FStreamingPauseRenderingModule, FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::*)() PtrMemFun = 58 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, FStreamingPauseRenderingModule *& Callable = 0x00000072f9190e80) Line 64 c++ libUE4.so!decltype(auto) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&) const(const UE4Tuple_Private::TTupleBase<TIntegerSequence<> > * this = 0x0000007209cb7b58, void (FStreamingPauseRenderingModule::*const &)() Func = 0x0000007209cb7b70, FStreamingPauseRenderingModule *& Args = 0x00000072f9190e80) Line 298 c++ libUE4.so!TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (), FDefaultDelegateUserPolicy>::Execute() const(TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (), FDefaultDelegateUserPolicy> * this = 0x0000007209cb7b50) Line 451 c++ libUE4.so!TDelegate<void (), FDefaultDelegateUserPolicy>::Execute() const(const TDelegate<void (), FDefaultDelegateUserPolicy> * this = 0x000000734d041e58) Line 579 c++ libUE4.so!UEngine::BlockTillLevelStreamingCompleted(UMyGameEngine * this = 0x000000734d03b010, UWorld * InWorld = 0x0000007209c0b210) Line 13824 c++ libUE4.so!AGameMode::HandleMatchHasStarted(AGameMode * this = 0x0000007240616a10) Line 236 c++ libUE4.so!AGameMode::OnMatchStateSet(AGameMode * this = 0x0000007240616a10) Line 386 c++ libUE4.so!AGameMode::SetMatchState(AGameMode * this = 0x0000007240616a10, FName NewState = ) Line 365 c++ libUE4.so!AGameMode::StartMatch(AGameMode * this = 0x0000007240616a10) Line 214 c++ libUE4.so!AGameMode::StartPlay(AGameMode * this = 0x0000007240616a10) Line 158 c++ libUE4.so!UWorld::BeginPlay(UWorld * this = 0x0000007209c0b210) Line 4602 c++ libUE4.so!UEngine::LoadMap(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , UPendingNetGame * Pending = 0x0000000000000000, FString & Error = 0x00000072f9192888) Line 13729 c++ libUE4.so!UEngine::Browse(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , FString & Error = 0x00000072f9192888) Line 12891 c++ libUE4.so!UEngine::TickWorldTravel(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & Context = 0x00000072085f6210, float DeltaSeconds = 20.7358685) Line 13089 c++ libUE4.so!UGameEngine::Tick(UMyGameEngine * this = 0x000000734d03b010, float DeltaSeconds = 20.7358685, bool bIdleMode = false) Line 1836 c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072a3166bc0) Line 4903 c++ libUE4.so!AndroidMain(android_app * state = 0x000000734cc7dd80) Line 581 c++ libUE4.so!android_main(android_app * state = 0x000000734cc7dd80) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x000000734cc7dd80) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown // 创建渲染线程 > libUE4.so!StartRenderingThread() Line 734 c++ libUE4.so!FSuspendRenderingThread::~FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072f9190b80) Line 197 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x00000072080b2210, bool bDestroyed = true, uint32 NewSizeX = 0, uint32 NewSizeY = 0, EWindowMode::Type NewWindowMode = Windowed, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1697 c++ libUE4.so!FSceneViewport::Destroy(FSceneViewport * this = 0x00000072080b2210) Line 175 c++ libUE4.so!FSceneViewport::~FSceneViewport(FSceneViewport * this = 0x00000072080b2210) Line 77 c++ libUE4.so!FSceneViewport::~FSceneViewport(FSceneViewport * this = 0x00000072080b2210) Line 76 c++ libUE4.so!SharedPointerInternals::DefaultDeleter<FSceneViewport>::operator()(FSceneViewport*) const(const SharedPointerInternals::DefaultDeleter<FSceneViewport> * this = 0x000000723f62fa50, FSceneViewport * Object = 0x00000072080b2210) Line 163 c++ libUE4.so!SharedPointerInternals::TReferenceControllerWithDeleter<FSceneViewport, SharedPointerInternals::DefaultDeleter<FSceneViewport>>::DestroyObject(SharedPointerInternals::TReferenceControllerWithDeleter<FSceneViewport, SharedPointerInternals::DefaultDeleter<FSceneViewport> > * this = 0x000000723f62fa50) Line 115 c++ libUE4.so!SharedPointerInternals::FReferenceControllerOps<(ESPMode)1>::ReleaseSharedReference(SharedPointerInternals::FReferenceControllerBase * ReferenceController = 0x000000723f62fa50) Line 281 c++ libUE4.so!SharedPointerInternals::FSharedReferencer<(ESPMode)1>::operator=(SharedPointerInternals::FSharedReferencer<ESPMode::Fast> * this = 0x000000734d041e20, SharedPointerInternals::FSharedReferencer<ESPMode::Fast> && InSharedReference = 0x00000072f9190d30) Line 515 c++ libUE4.so!TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(TSharedPtr<FSceneViewport, ESPMode::Fast> * this = 0x000000734d041e18, TSharedPtr<FSceneViewport, ESPMode::Fast> && InSharedPtr = 0x00000072f9190d28) Line 790 c++ libUE4.so!TSharedPtr<FSceneViewport, (ESPMode)1>::Reset(TSharedPtr<FSceneViewport, ESPMode::Fast> * this = 0x000000734d041e18) Line 899 c++ libUE4.so!TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(TSharedPtr<FSceneViewport, ESPMode::Fast> * this = 0x000000734d041e18, SharedPointerInternals::FNullTag * = 0x0000000000000000) Line 766 c++ libUE4.so!FStreamingPauseRenderingModule::EndStreamingPause(FStreamingPauseRenderingModule * this = 0x000000734d041e10) Line 173 c++ libUE4.so!decltype(UE4Invoke_Private::DereferenceIfNecessary<FStreamingPauseRenderingModule>(Forward<FStreamingPauseRenderingModule*&>(fp0)).*fp()) Invoke<void, FStreamingPauseRenderingModule, FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::*)() PtrMemFun = 58 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, FStreamingPauseRenderingModule *& Callable = 0x00000072f9190e80) Line 64 c++ libUE4.so!decltype(auto) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&) const(const UE4Tuple_Private::TTupleBase<TIntegerSequence<> > * this = 0x0000007209cb7b58, void (FStreamingPauseRenderingModule::*const &)() Func = 0x0000007209cb7b70, FStreamingPauseRenderingModule *& Args = 0x00000072f9190e80) Line 298 c++ libUE4.so!TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (), FDefaultDelegateUserPolicy>::Execute() const(TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (), FDefaultDelegateUserPolicy> * this = 0x0000007209cb7b50) Line 451 c++ libUE4.so!TDelegate<void (), FDefaultDelegateUserPolicy>::Execute() const(const TDelegate<void (), FDefaultDelegateUserPolicy> * this = 0x000000734d041e58) Line 579 c++ libUE4.so!UEngine::BlockTillLevelStreamingCompleted(UMyGameEngine * this = 0x000000734d03b010, UWorld * InWorld = 0x0000007209c0b210) Line 13824 c++ libUE4.so!AGameMode::HandleMatchHasStarted(AGameMode * this = 0x0000007240616a10) Line 236 c++ libUE4.so!AGameMode::OnMatchStateSet(AGameMode * this = 0x0000007240616a10) Line 386 c++ libUE4.so!AGameMode::SetMatchState(AGameMode * this = 0x0000007240616a10, FName NewState = ) Line 365 c++ libUE4.so!AGameMode::StartMatch(AGameMode * this = 0x0000007240616a10) Line 214 c++ libUE4.so!AGameMode::StartPlay(AGameMode * this = 0x0000007240616a10) Line 158 c++ libUE4.so!UWorld::BeginPlay(UWorld * this = 0x0000007209c0b210) Line 4602 c++ libUE4.so!UEngine::LoadMap(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , UPendingNetGame * Pending = 0x0000000000000000, FString & Error = 0x00000072f9192888) Line 13729 c++ libUE4.so!UEngine::Browse(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & WorldContext = 0x00000072085f6210, FURL URL = , FString & Error = 0x00000072f9192888) Line 12891 c++ libUE4.so!UEngine::TickWorldTravel(UMyGameEngine * this = 0x000000734d03b010, FWorldContext & Context = 0x00000072085f6210, float DeltaSeconds = 20.7358685) Line 13089 c++ libUE4.so!UGameEngine::Tick(UMyGameEngine * this = 0x000000734d03b010, float DeltaSeconds = 20.7358685, bool bIdleMode = false) Line 1836 c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072a3166bc0) Line 4903 c++ libUE4.so!AndroidMain(android_app * state = 0x000000734cc7dd80) Line 581 c++ libUE4.so!android_main(android_app * state = 0x000000734cc7dd80) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x000000734cc7dd80) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown
iOS堆栈:
// 销毁渲染线程 * frame #0: 0x000000010b308d7c MyGame`StopRenderingThread() at RenderingThread.cpp:813:2 frame #1: 0x000000010b308a9c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x00000001703443a1, bInRecreateThread=true) at RenderingThread.cpp:125:3 frame #2: 0x000000010b30968c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x00000001703443a1, bInRecreateThread=true) at RenderingThread.cpp:109:1 frame #3: 0x000000010e41ea68 MyGame`FSceneViewport::UpdateViewportRHI(this=0x00000002d1d90180, bDestroyed=true, NewSizeX=0, NewSizeY=0, NewWindowMode=Windowed, PreferredPixelFormat=PF_Unknown) at SceneViewport.cpp:1648:3 frame #4: 0x000000010e4176b8 MyGame`FSceneViewport::Destroy(this=0x00000002d1d90180) at SceneViewport.cpp:176:2 frame #5: 0x000000010e416cb4 MyGame`FSceneViewport::~FSceneViewport(this=0x00000002d1d90180) at SceneViewport.cpp:78:2 frame #6: 0x000000010e416edc MyGame`FSceneViewport::~FSceneViewport(this=0x00000002d1d90180) at SceneViewport.cpp:77:1 frame #7: 0x000000010e416f5c MyGame`FSceneViewport::~FSceneViewport(this=0x00000002d1d90180) at SceneViewport.cpp:77:1 frame #8: 0x000000010cceb218 MyGame`SharedPointerInternals::DefaultDeleter<FSceneViewport>::operator(this=0x000000029feaecc0, Object=0x00000002d1d90180)(FSceneViewport*) const at SharedPointerInternals.h:164:4 frame #9: 0x000000010cceb17c MyGame`SharedPointerInternals::TReferenceControllerWithDeleter<FSceneViewport, SharedPointerInternals::DefaultDeleter<FSceneViewport> >::DestroyObject(this=0x000000029feaecc0) at SharedPointerInternals.h:116:4 frame #10: 0x0000000104b24a50 MyGame`SharedPointerInternals::FReferenceControllerOps<(ESPMode)1>::ReleaseSharedReference(ReferenceController=0x000000029feaecc0) at SharedPointerInternals.h:282:26 frame #11: 0x0000000104b41064 MyGame`SharedPointerInternals::FSharedReferencer<(ESPMode)1>::operator=(this=0x00000002811d1630, InSharedReference=0x0000000170344570)1>&&) at SharedPointerInternals.h:516:6 frame #12: 0x000000010cceb3e4 MyGame`TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(this=0x00000002811d1628, InSharedPtr=0x0000000170344568)1>&&) at SharedPointer.h:791:25 frame #13: 0x000000010d1aebc4 MyGame`TSharedPtr<FSceneViewport, (ESPMode)1>::Reset(this=0x00000002811d1628) at SharedPointer.h:900:10 frame #14: 0x000000010d1ab848 MyGame`TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(this=0x00000002811d1628, (null)=0x0000000000000000) at SharedPointer.h:767:3 frame #15: 0x000000010d1ab7c4 MyGame`FStreamingPauseRenderingModule::EndStreamingPause(this=0x00000002811d1620) at StreamingPauseRendering.cpp:174:17 frame #16: 0x000000010d1ad7e4 MyGame`decltype(PtrMemFun=58 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, Callable=0x00000001703446a0)).*fp()) Invoke<void, FStreamingPauseRenderingModule, FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::*)(), FStreamingPauseRenderingModule*&) at Invoke.h:65:9 frame #17: 0x000000010d1ad758 MyGame`decltype(this=0x0000000282886e58, Func=0x0000000282886e70, Args=0x00000001703446a0) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int> >::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&) const at Tuple.h:299:11 frame #18: 0x000000010d1ad574 MyGame`TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (), FDefaultDelegateUserPolicy>::Execute(this=0x0000000282886e50) const at DelegateInstancesImpl.h:452:24 frame #19: 0x0000000104fdd9c0 MyGame`TDelegate<void (), FDefaultDelegateUserPolicy>::Execute(this=0x00000002811d1668) const at DelegateSignatureImpl.inl:580:33 frame #20: 0x000000010d293f9c MyGame`UEngine::BlockTillLevelStreamingCompleted(this=0x0000000144e70200, InWorld=0x0000000144c49600) at UnrealEngine.cpp:13825:40 frame #21: 0x000000010da6ba08 MyGame`AGameMode::HandleMatchHasStarted(this=0x000000016e126a00) at GameMode.cpp:237:12 frame #22: 0x000000010da6c694 MyGame`AGameMode::OnMatchStateSet(this=0x000000016e126a00) at GameMode.cpp:387:3 frame #23: 0x000000010da6c22c MyGame`AGameMode::SetMatchState(this=0x000000016e126a00, NewState=name=b'InProgress') at GameMode.cpp:366:2 frame #24: 0x000000010da6b8f8 MyGame`AGameMode::StartMatch(this=0x000000016e126a00) at GameMode.cpp:215:2 frame #25: 0x000000010da6b734 MyGame`AGameMode::StartPlay(this=0x000000016e126a00) at GameMode.cpp:159:3 frame #26: 0x000000010e746a84 MyGame`UWorld::BeginPlay(this=0x0000000144c49600) at World.cpp:4603:13 frame #27: 0x000000010d2917b8 MyGame`UEngine::LoadMap(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x00000001703457b0, Pending=0x0000000000000000, Error=string=None) at UnrealEngine.cpp:13730:24 frame #28: 0x000000010d28db2c MyGame`UEngine::Browse(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x0000000170345ca0, Error=string=None) at UnrealEngine.cpp:12892:10 frame #29: 0x000000010d28f358 MyGame`UEngine::TickWorldTravel(this=0x0000000144e70200, Context=0x000000016635cc90, DeltaSeconds=10.3148842) at UnrealEngine.cpp:13090:7 frame #30: 0x000000010da26f20 MyGame`UGameEngine::Tick(this=0x0000000144e70200, DeltaSeconds=10.3148842, bIdleMode=false) at GameEngine.cpp:1837:4 frame #31: 0x0000000104b09578 MyGame`FEngineLoop::Tick(this=0x0000000112c51400) at LaunchEngineLoop.cpp:4904:12 frame #32: 0x0000000104b08624 MyGame`FAppEntry::Tick() at LaunchIOS.cpp:523:14 frame #33: 0x000000010a7df8d4 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:562:13 frame #34: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #35: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148 // 创建渲染线程 * frame #0: 0x000000010b3098d0 MyGame`StartRenderingThread() at RenderingThread.cpp:735:2 frame #1: 0x000000010b309710 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x00000001703443a1) at RenderingThread.cpp:198:4 frame #2: 0x000000010b309e40 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x00000001703443a1) at RenderingThread.cpp:191:1 frame #3: 0x000000010e41ec18 MyGame`FSceneViewport::UpdateViewportRHI(this=0x00000002d1d90180, bDestroyed=true, NewSizeX=0, NewSizeY=0, NewWindowMode=Windowed, PreferredPixelFormat=PF_Unknown) at SceneViewport.cpp:1698:2 frame #4: 0x000000010e4176b8 MyGame`FSceneViewport::Destroy(this=0x00000002d1d90180) at SceneViewport.cpp:176:2 frame #5: 0x000000010e416cb4 MyGame`FSceneViewport::~FSceneViewport(this=0x00000002d1d90180) at SceneViewport.cpp:78:2 frame #6: 0x000000010e416edc MyGame`FSceneViewport::~FSceneViewport(this=0x00000002d1d90180) at SceneViewport.cpp:77:1 frame #7: 0x000000010e416f5c MyGame`FSceneViewport::~FSceneViewport(this=0x00000002d1d90180) at SceneViewport.cpp:77:1 frame #8: 0x000000010cceb218 MyGame`SharedPointerInternals::DefaultDeleter<FSceneViewport>::operator(this=0x000000029feaecc0, Object=0x00000002d1d90180)(FSceneViewport*) const at SharedPointerInternals.h:164:4 frame #9: 0x000000010cceb17c MyGame`SharedPointerInternals::TReferenceControllerWithDeleter<FSceneViewport, SharedPointerInternals::DefaultDeleter<FSceneViewport> >::DestroyObject(this=0x000000029feaecc0) at SharedPointerInternals.h:116:4 frame #10: 0x0000000104b24a50 MyGame`SharedPointerInternals::FReferenceControllerOps<(ESPMode)1>::ReleaseSharedReference(ReferenceController=0x000000029feaecc0) at SharedPointerInternals.h:282:26 frame #11: 0x0000000104b41064 MyGame`SharedPointerInternals::FSharedReferencer<(ESPMode)1>::operator=(this=0x00000002811d1630, InSharedReference=0x0000000170344570)1>&&) at SharedPointerInternals.h:516:6 frame #12: 0x000000010cceb3e4 MyGame`TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(this=0x00000002811d1628, InSharedPtr=0x0000000170344568)1>&&) at SharedPointer.h:791:25 frame #13: 0x000000010d1aebc4 MyGame`TSharedPtr<FSceneViewport, (ESPMode)1>::Reset(this=0x00000002811d1628) at SharedPointer.h:900:10 frame #14: 0x000000010d1ab848 MyGame`TSharedPtr<FSceneViewport, (ESPMode)1>::operator=(this=0x00000002811d1628, (null)=0x0000000000000000) at SharedPointer.h:767:3 frame #15: 0x000000010d1ab7c4 MyGame`FStreamingPauseRenderingModule::EndStreamingPause(this=0x00000002811d1620) at StreamingPauseRendering.cpp:174:17 frame #16: 0x000000010d1ad7e4 MyGame`decltype(PtrMemFun=58 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00, Callable=0x00000001703446a0)).*fp()) Invoke<void, FStreamingPauseRenderingModule, FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::*)(), FStreamingPauseRenderingModule*&) at Invoke.h:65:9 frame #17: 0x000000010d1ad758 MyGame`decltype(this=0x0000000282886e58, Func=0x0000000282886e70, Args=0x00000001703446a0) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int> >::ApplyAfter<void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&>(void (FStreamingPauseRenderingModule::* const&)(), FStreamingPauseRenderingModule*&) const at Tuple.h:299:11 frame #18: 0x000000010d1ad574 MyGame`TBaseRawMethodDelegateInstance<false, FStreamingPauseRenderingModule, void (), FDefaultDelegateUserPolicy>::Execute(this=0x0000000282886e50) const at DelegateInstancesImpl.h:452:24 frame #19: 0x0000000104fdd9c0 MyGame`TDelegate<void (), FDefaultDelegateUserPolicy>::Execute(this=0x00000002811d1668) const at DelegateSignatureImpl.inl:580:33 frame #20: 0x000000010d293f9c MyGame`UEngine::BlockTillLevelStreamingCompleted(this=0x0000000144e70200, InWorld=0x0000000144c49600) at UnrealEngine.cpp:13825:40 frame #21: 0x000000010da6ba08 MyGame`AGameMode::HandleMatchHasStarted(this=0x000000016e126a00) at GameMode.cpp:237:12 frame #22: 0x000000010da6c694 MyGame`AGameMode::OnMatchStateSet(this=0x000000016e126a00) at GameMode.cpp:387:3 frame #23: 0x000000010da6c22c MyGame`AGameMode::SetMatchState(this=0x000000016e126a00, NewState=name=b'InProgress') at GameMode.cpp:366:2 frame #24: 0x000000010da6b8f8 MyGame`AGameMode::StartMatch(this=0x000000016e126a00) at GameMode.cpp:215:2 frame #25: 0x000000010da6b734 MyGame`AGameMode::StartPlay(this=0x000000016e126a00) at GameMode.cpp:159:3 frame #26: 0x000000010e746a84 MyGame`UWorld::BeginPlay(this=0x0000000144c49600) at World.cpp:4603:13 frame #27: 0x000000010d2917b8 MyGame`UEngine::LoadMap(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x00000001703457b0, Pending=0x0000000000000000, Error=string=None) at UnrealEngine.cpp:13730:24 frame #28: 0x000000010d28db2c MyGame`UEngine::Browse(this=0x0000000144e70200, WorldContext=0x000000016635cc90, URL=FURL @ 0x0000000170345ca0, Error=string=None) at UnrealEngine.cpp:12892:10 frame #29: 0x000000010d28f358 MyGame`UEngine::TickWorldTravel(this=0x0000000144e70200, Context=0x000000016635cc90, DeltaSeconds=10.3148842) at UnrealEngine.cpp:13090:7 frame #30: 0x000000010da26f20 MyGame`UGameEngine::Tick(this=0x0000000144e70200, DeltaSeconds=10.3148842, bIdleMode=false) at GameEngine.cpp:1837:4 frame #31: 0x0000000104b09578 MyGame`FEngineLoop::Tick(this=0x0000000112c51400) at LaunchEngineLoop.cpp:4904:12 frame #32: 0x0000000104b08624 MyGame`FAppEntry::Tick() at LaunchIOS.cpp:523:14 frame #33: 0x000000010a7df8d4 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:562:13 frame #34: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #35: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148
修改BackBuffer大小时,销毁并重新创建渲染线程
通过SCOPED_SUSPEND_RENDERING_THREAD(true)的RAII机制来实现
Android可通过r.MobileContentScaleFactor 1.5控制台命令来动态修改BufferBack的大小;iOS则不能动态修改,只能在启动时读取r.MobileContentScaleFactor的值或通过命令行参数mcsf=xx来修改。
// 销毁渲染线程 > libUE4.so!StopRenderingThread() Line 812 c++ libUE4.so!FSuspendRenderingThread::FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072c58ec4d0, bool bInRecreateThread = true) Line 124 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x0000007249ee5710, bool bDestroyed = false, uint32 NewSizeX = 1552, uint32 NewSizeY = 720, EWindowMode::Type NewWindowMode = Fullscreen, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1647 c++ libUE4.so!FSceneViewport::ResizeViewport(FSceneViewport * this = 0x0000007249ee5710, uint32 NewSizeX = 1552, uint32 NewSizeY = 720, EWindowMode::Type NewWindowMode = Fullscreen) Line 1545 c++ libUE4.so!FSceneViewport::ResizeFrame(FSceneViewport * this = 0x0000007249ee5710, uint32 NewWindowSizeX = 1552, uint32 NewWindowSizeY = 720, EWindowMode::Type NewWindowMode = Fullscreen) Line 1448 c++ libUE4.so!SystemResolutionSinkCallback() Line 856 c++ libUE4.so!RefreshEngineSettings() Line 953 c++ libUE4.so!decltype(Forward<void (* const&)()>(fp)()) Invoke<void (* const&)()>(void (*const &)() Func = 0x00000072c3441ca8) Line 50 c++ libUE4.so!decltype(auto) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter<void (* const&)()>(void (* const&)()) const(const UE4Tuple_Private::TTupleBase<TIntegerSequence<> > * this = 0x00000072c3441c98, void (*const &)() Func = 0x00000072c3441ca8) Line 298 c++ libUE4.so!TBaseStaticDelegateInstance<void (), FDefaultDelegateUserPolicy>::ExecuteIfSafe() const(TBaseStaticDelegateInstance<void (), FDefaultDelegateUserPolicy> * this = 0x00000072c3441c90) Line 728 c++ libUE4.so!bool TDelegate<void (), FDefaultDelegateUserPolicy>::ExecuteIfBound<void, (void*)0>() const(const TDelegate<void (), FDefaultDelegateUserPolicy> * this = 0x00000072e424c1b0) Line 598 c++ libUE4.so!FConsoleManager::CallAllConsoleVariableSinks(FConsoleManager * this = 0x000000734268b9d0) Line 801 c++ libUE4.so!FSlateRHIRenderer::SetSystemResolution(FSlateRHIRenderer * this = 0x0000007349180a90, uint32 Width = 1552, uint32 Height = 720) Line 518 c++ libUE4.so!FSlateApplication::OnSizeChanged(FSlateApplication * this = 0x00000072621bfb10, const TSharedRef<FGenericWindow, ESPMode::Fast> & PlatformWindow = 0x00000072c58eccc0, int32 Width = 1552, int32 Height = 720, bool bWasMinimized = false) Line 6218 c++ libUE4.so!non-virtual thunk to FSlateApplication::OnSizeChanged(FSlateApplication * this = 0x00000072621bfb10, const TSharedRef<FGenericWindow, ESPMode::Fast> & PlatformWindow = 0x00000072c58eccc0, int32 Width = 1552, int32 Height = 720, bool bWasMinimized = false) c++ libUE4.so!FAndroidApplication::PollGameDeviceState(FAndroidApplication * this = 0x00000073488ebbf0, const float TimeDelta = 0.0334545299) Line 175 c++ libUE4.so!FSlateApplication::PollGameDeviceState(FSlateApplication * this = 0x00000072621bfb10) Line 1396 c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072bc7b8bc0) Line 4882 c++ libUE4.so!AndroidMain(android_app * state = 0x00000072e4117300) Line 581 c++ libUE4.so!android_main(android_app * state = 0x00000072e4117300) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x00000072e4117300) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown // 创建渲染线程 > libUE4.so!StartRenderingThread() Line 734 c++ libUE4.so!FSuspendRenderingThread::~FSuspendRenderingThread(FSuspendRenderingThread * this = 0x00000072c58ec4d0) Line 197 c++ libUE4.so!FSceneViewport::UpdateViewportRHI(FSceneViewport * this = 0x0000007249ee5710, bool bDestroyed = false, uint32 NewSizeX = 1552, uint32 NewSizeY = 720, EWindowMode::Type NewWindowMode = Fullscreen, EPixelFormat PreferredPixelFormat = PF_Unknown) Line 1697 c++ libUE4.so!FSceneViewport::ResizeViewport(FSceneViewport * this = 0x0000007249ee5710, uint32 NewSizeX = 1552, uint32 NewSizeY = 720, EWindowMode::Type NewWindowMode = Fullscreen) Line 1545 c++ libUE4.so!FSceneViewport::ResizeFrame(FSceneViewport * this = 0x0000007249ee5710, uint32 NewWindowSizeX = 1552, uint32 NewWindowSizeY = 720, EWindowMode::Type NewWindowMode = Fullscreen) Line 1448 c++ libUE4.so!SystemResolutionSinkCallback() Line 856 c++ libUE4.so!RefreshEngineSettings() Line 953 c++ libUE4.so!decltype(Forward<void (* const&)()>(fp)()) Invoke<void (* const&)()>(void (*const &)() Func = 0x00000072c3441ca8) Line 50 c++ libUE4.so!decltype(auto) UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter<void (* const&)()>(void (* const&)()) const(const UE4Tuple_Private::TTupleBase<TIntegerSequence<> > * this = 0x00000072c3441c98, void (*const &)() Func = 0x00000072c3441ca8) Line 298 c++ libUE4.so!TBaseStaticDelegateInstance<void (), FDefaultDelegateUserPolicy>::ExecuteIfSafe() const(TBaseStaticDelegateInstance<void (), FDefaultDelegateUserPolicy> * this = 0x00000072c3441c90) Line 728 c++ libUE4.so!bool TDelegate<void (), FDefaultDelegateUserPolicy>::ExecuteIfBound<void, (void*)0>() const(const TDelegate<void (), FDefaultDelegateUserPolicy> * this = 0x00000072e424c1b0) Line 598 c++ libUE4.so!FConsoleManager::CallAllConsoleVariableSinks(FConsoleManager * this = 0x000000734268b9d0) Line 801 c++ libUE4.so!FSlateRHIRenderer::SetSystemResolution(FSlateRHIRenderer * this = 0x0000007349180a90, uint32 Width = 1552, uint32 Height = 720) Line 518 c++ libUE4.so!FSlateApplication::OnSizeChanged(FSlateApplication * this = 0x00000072621bfb10, const TSharedRef<FGenericWindow, ESPMode::Fast> & PlatformWindow = 0x00000072c58eccc0, int32 Width = 1552, int32 Height = 720, bool bWasMinimized = false) Line 6218 c++ libUE4.so!non-virtual thunk to FSlateApplication::OnSizeChanged(FSlateApplication * this = 0x00000072621bfb10, const TSharedRef<FGenericWindow, ESPMode::Fast> & PlatformWindow = 0x00000072c58eccc0, int32 Width = 1552, int32 Height = 720, bool bWasMinimized = false) c++ libUE4.so!FAndroidApplication::PollGameDeviceState(FAndroidApplication * this = 0x00000073488ebbf0, const float TimeDelta = 0.0334545299) Line 175 c++ libUE4.so!FSlateApplication::PollGameDeviceState(FSlateApplication * this = 0x00000072621bfb10) Line 1396 c++ libUE4.so!FEngineLoop::Tick(FEngineLoop * this = 0x00000072bc7b8bc0) Line 4882 c++ libUE4.so!AndroidMain(android_app * state = 0x00000072e4117300) Line 581 c++ libUE4.so!android_main(android_app * state = 0x00000072e4117300) Line 826 c++ libUE4.so!android_app_entry(void * param = 0x00000072e4117300) Line 232 c99 libc.so!__pthread_start() unknown libc.so!__start_thread() unknown
注:BackBuffer大小改变时,FSceneViewport::UpdateViewportRHI函数会派发ViewportResizedEvent代理 // FOnViewportResized ViewportResizedEvent
iOS切前后台,销毁并重新创建渲染线程
切后台
* frame #0: 0x000000010b308d7c MyGame`StopRenderingThread() at RenderingThread.cpp:813:2 frame #1: 0x000000010b308a9c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x0000000283866880, bInRecreateThread=true) at RenderingThread.cpp:125:3 frame #2: 0x000000010b30968c MyGame`FSuspendRenderingThread::FSuspendRenderingThread(this=0x0000000283866880, bInRecreateThread=true) at RenderingThread.cpp:109:1 frame #3: 0x0000000104b0a288 MyGame`FAppEntry::SuspendTick() at LaunchIOS.cpp:549:23 frame #4: 0x000000010a7df668 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:507:13 frame #5: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #6: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148
切回前台
* frame #0: 0x000000010b3098d0 MyGame`StartRenderingThread() at RenderingThread.cpp:735:2 frame #1: 0x000000010b309710 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x0000000283866880) at RenderingThread.cpp:198:4 frame #2: 0x000000010b309e40 MyGame`FSuspendRenderingThread::~FSuspendRenderingThread(this=0x0000000283866880) at RenderingThread.cpp:191:1 frame #3: 0x0000000104b085b8 MyGame`FAppEntry::Tick() at LaunchIOS.cpp:507:3 frame #4: 0x000000010a7df8d4 MyGame`-[IOSAppDelegate MainAppThread:](self=0x000000028003bc20, _cmd="MainAppThread:", launchOptions=0x0000000000000000) at IOSAppDelegate.cpp:562:13 frame #5: 0x00000001831f236c Foundation`__NSThread__start__ + 808 frame #6: 0x00000001f258a9a4 libsystem_pthread.dylib`_pthread_start + 148
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2021-10-21 Android Studio Profiler(Native Memory)