x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

[Closed] Slate? Garbage collection crash during map tranistion

We are seeing an occasional garbage collection crash when transitioning from our game play maps back to our front end maps during the garbage collection after everything is destroyed

 UE4Editor-Engine.dll!internalCheckObjectPointer(UObject * p, UClass * pClass)
 UE4Editor-SlateRHIRenderer.dll!FSlateBaseUTextureResource::AccessRHIResource()
 UE4Editor-SlateRHIRenderer.dll!FSlateRHIRenderingPolicy::DrawElements(FRHICommandListImmediate & RHICmdList, FSlateBackBuffer & BackBuffer, const FMatrix & ViewProjectionMatrix, const TArray & RenderBatches, bool bAllowSwitchVerticalAxis)
 UE4Editor-SlateRHIRenderer.dll!FSlateRHIRenderer::DrawWindow_RenderThread(FRHICommandListImmediate & RHICmdList, const FSlateRHIRenderer::FViewportInfo & ViewportInfo, FSlateWindowElementList & WindowElementList, bool bLockToVsync, bool bClear) 
 UE4Editor-SlateRHIRenderer.dll!TGraphTask<`FSlateRHIRenderer::DrawWindows_Private'::`33'::EURCMacro_SlateDrawWindowsCommand>::ExecuteTask(TArray & NewTasks, ENamedThreads::Type CurrentThread)
 UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksNamedThread(int QueueIndex, bool bAllowStall)
 UE4Editor-Core.dll!FNamedTaskThread::ProcessTasksUntilQuit(int QueueIndex)
 UE4Editor-RenderCore.dll!RenderingThreadMain(FEvent * TaskGraphBoundSyncEvent)
 UE4Editor-RenderCore.dll!FRenderingThread::Run()
 UE4Editor-Core.dll!FRunnableThreadWin::Run()
 UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun()

 

We are looking into this but wondering if this looks familiar?

Product Version: Not Selected
Tags:
more ▼

asked Dec 09 '16 at 10:08 PM in C++ Programming

avatar image

Answers.Archive STAFF
1.9k 210 316 690

avatar image Answers.Archive STAFF Dec 09 '16 at 10:08 PM

Hmm looks like I've narrowed this down to the loading screen which we just brought over from the shooter game example on like version 4.9 and haven't touched since.

avatar image Answers.Archive STAFF Dec 09 '16 at 10:08 PM

Well I have narrowed the problem down to this function when slate paints

FSlateShaderResourceProxy* FSlateRHIResourceManager::FindOrCreateDynamicTextureResource(const FSlateBrush& InBrush)

Specifically line 660

TSharedPtr TextureResource = DynamicResourceMap.GetUTextureResource(TextureObject);

It looks like the DynamicResourceMap will find a stale entry for my texture object. I'm not exactly sure why though as all the Keys display as STALE in the debugger. But it possibly could be a side effect of the Garbage Collection that is occuring while the map is transitioning

avatar image Answers.Archive STAFF Dec 09 '16 at 10:09 PM

Hi Eric,

Sorry for the delay, I'm looking in to this for you. Can you post the code that you're using to invoke the loading screen? Are you using seamless travel? It does sound like something is causing GC to wipe out textures being used by your loading screen.

avatar image Answers.Archive STAFF Dec 09 '16 at 10:09 PM

Hi Cody,

The code is virtually a copy and paste from the shooter game except we are not using a separate module for the loading screen. But anyways I'm registering for preload map

 void UOurGameInstance::Init()
 {
     FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &UOurGameInstance::BeginLoadingScreen);
 }
     
 void UOurGameInstance::BeginLoadingScreen(const FString& MapName)
 {
     FLoadingScreenAttributes LoadingScreen;
     LoadingScreen.bAutoCompleteWhenLoadingCompletes = false;
     LoadingScreen.WidgetLoadingScreen = SNew( SOurLoadingScreen );
      
     GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
 }

The loading screen is defined like so

 struct FOurLoadingScreenBrush : public FSlateDynamicImageBrush, public FGCObject
 {
     FOurLoadingScreenBrush( const FName InTextureName, const FVector2D& InImageSize )
         : FSlateDynamicImageBrush( InTextureName, InImageSize )
     {
         ResourceObject = LoadObject( NULL, *InTextureName.ToString() );
     }
 
     virtual void AddReferencedObjects(FReferenceCollector& Collector)
     {
         if( ResourceObject )
         {
             Collector.AddReferencedObject(ResourceObject);
         }
     }
 };
 
 class SOurLoadingScreen : public SCompoundWidget
 {
 public:
     SLATE_BEGIN_ARGS(SOurLoadingScreen) {}
     SLATE_END_ARGS()
 
     void Construct(const FArguments& InArgs);
 
 private:
     EVisibility GetLoadIndicatorVisibility() const
     {
         return EVisibility::Visible;
     }
 
     /** loading screen image brush */
     TSharedPtr LoadingScreenBrush;
 };


What I'm finding though is FOurLoadingScreenBrush::AddReferencedObjects isn't initially being called until after FSlateRHIResourceManager::FindOrCreateDynamicTextureResource. I assume the calls are made on different threads. So on that first frame the texture object in the slate brush is falsely considered invalid. So it picks the first invalid object in the DynamicResourceMap as it's resource. I assume AddReferencedObjects does some registration with GC so it knows about objects held with shared pointers. This seems to be coming too late and the object is considered invalid by GC and subsequently by "weak pointer == comparisons", which is the keys used by the DynamicResourceMap. FYI, I can really only get this to appear when running the editor in development with the -game flag

avatar image Answers.Archive STAFF Dec 09 '16 at 10:08 PM

I'm wondering if 2 stale/invalid weak pointers should be considered equal. The concept seems...not right. They could be completely different invalid/stale weak pointers that used to hold completely different things. Does invalidating both now make them equal?

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

The question has been closed Dec 09 '16 at 10:09 PM by AndrewHurley for the following reason:

The question is answered, right answer was accepted


1 answer: sort voted first

Hi Eric,

It's possible that this is an issue stemming from your resource UObject being managed in your loading screen thread. Try removing the FGCObject inheritance, and calling AddToRoot right after creating the ResourceObject to ensure it won't be garbage collected. You'll then need to call RemoveFromRoot once the loading screen is destroyed.

Let me know if that works for you, otherwise we'll keep digging.

Best,

Cody

more ▼

answered Dec 09 '16 at 10:09 PM

avatar image

Answers.Archive STAFF
1.9k 210 316 690

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question