可可西

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

 

posted on   可可西  阅读(326)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2021-10-21 Android Studio Profiler(Native Memory)

导航

统计信息

点击右上角即可分享
微信分享提示