FRayTracingGeometryManager::Tick() double call issue

This question was created in reference to: [checkf in [Content removed]

As the linked issue mentioned, I’m encountering an issue with RaytracingGeometryManager thinking that it is called 2x in 1 frame.

> checkf(GFrameCounterRenderThread != PreviousFrameCounter, TEXT(“FRayTracingGeometryManager::Tick() should only be called once per frame”));

And tied to this bug report:

> Unreal Engine Issues and Bug Tracker (UE-254119

This started happening to us in our integration branch for 5.6, right on boot during the movie logo phase. After some investigation, I was able to track it down to the code below.

The sum up, the movie player is in a loop that’s ticking the engine, which enqueue a RenderCommand to tick the GeoManager. Unfortunately the code doesn’t increment ‘GFrameCounterRenderThread’ which is tested by the GeoManager.

The fix I made is to set the value of GFrameCounterRenderThread with ‘GFrameCounter’ as I saw done in other locations. Does it makes sens?

void FDefaultGameMoviePlayer::WaitForMovieToFinish(bool bAllowEngineTick)
{
	const bool bEnforceMinimumTime = LoadingScreenAttributes.MinimumLoadingScreenDisplayTime >= 0.0f;
 
 
	if (LoadingScreenIsPrepared() && IsMovieCurrentlyPlaying())
	{
		//...
		// Continue to wait until the user calls finish (if enabled) or when loading completes or the minimum enforced time (if any) has been reached.
		// Don't continue playing on game shutdown
		while ( !IsEngineExitRequested() &&
				((bWaitForManualStop && !bUserCalledFinish)
			||	(!bUserCalledFinish && !bEnforceMinimumTime && !IsMovieStreamingFinished() && !bAutoCompleteWhenLoadingCompletes) 
			||	(bEnforceMinimumTime && (FPlatformTime::Seconds() - LastPlayTime) < LoadingScreenAttributes.MinimumLoadingScreenDisplayTime)))
		{
			//...
			if (FSlateApplication::IsInitialized())
			{
				//...
				if (GEngine && bAllowEngineTick && LoadingScreenAttributes.bAllowEngineTick)
				{
					//---------------------------------------------------------
					// NOTE: Calls 'FRendererModule::PostRenderAllViewports'
					// which enqueue the RenderThread GeometryManager::Tick
					//---------------------------------------------------------
					GEngine->Tick(DeltaTime, false);
				}
				//...
				FDefaultGameMoviePlayer* InMoviePlayer = this;
				ENQUEUE_RENDER_COMMAND(BeginLoadingMovieFrameAndTickMovieStreamer)(
					[InMoviePlayer, DeltaTime, CurrentFrameCounter = GFrameCounter](FRHICommandListImmediate& RHICmdList)
					{
						GFrameNumberRenderThread++;
						//---------------------------------------------------------
						// NOTE: Missing increment to 'GFrameCounterRenderThread'
						// which is checked by GeometryManager
						GFrameCounterRenderThread = CurrentFrameCounter;  // <=== THE FIX IS THIS
						//---------------------------------------------------------
						InMoviePlayer->TickStreamer(DeltaTime);
					}
				);
				//...
			}
		}
		//...
	}
}

Steps to Reproduce

Hi Sammy,

Thanks for reaching out about this. I have passed on the information to the dev team, which will take a look at your change as soon as possible. The code change seems trivial, so it would be a nice win if this fixes the double-ticking problem reported by other licensees. How did you narrow down the issue to this call site during your investigation?

In my case, it was fairly easy to narrow down because it happen 100% on boot, when displaying logo movies. I only had to find what was enqueuing the render command call FRayTracingGeometryManager::Tick and found this callstack:

> Game.exe!FRendererModule::PostRenderAllViewports() Line 5219 C++

Game.exe!UGameEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 2028 C++

Game.exe!FDefaultGameMoviePlayer::WaitForMovieToFinish(bool bAllowEngineTick) Line 684 C++

Game.exe!FEngineLoop::Init() Line 4941 C++

[Inline Frame] nGame.exe!EngineInit() Line 54 C++

Game.exe!GuardedMain(const wchar_t * CmdLine) Line 183 C++

Game.exe!LaunchWindowsStartup(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow, const wchar_t * CmdLine) Line 271 C++

Game.exe!WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * pCmdLine, int nCmdShow) Line 340 C++

Which then led me to see that the engine is ticked and ‘GFrameNumberRenderThread’ incremented in the ‘WaitForMovieToFinish’ loop, but not the ‘GFrameCounterRenderThread’ that’s actually tested by the FRayTracingGeometryManager. This might not fix all occurrence of this issue seen by other developers (engine is also ticked in other locations) but it fixed our current problem.

Thanks for the extra info. You are right that this change might not fix all instances of this double-ticking crash, but it is a good starting point since we have had a hard time reproducing this ourselves. I have passed on the ticket to the relevant developers now, but feel free to ping this thread if you have any further questions.