[4.5 Urgent] Cant upgrade Solus, Making an FCanvas for Render Texture Crashes 4.5, Same Code works great in 4.4

Dear Friends at Epic,

Hi there!

I just upgraded Solus to 4.5, and now the game is broken because I am creating FCanvas to render to from code.

The same code worked great in 4.4!

The constructor changed in 4.5, but other than that my code is the same as what worked in 4.4

#Code

void ASolusPDAButtonMesh::InitializeTextureRender(FVector2D IN_Dimensions)
{
	Dimensions = IN_Dimensions;
	
	RenderTex = CastChecked<UTextureRenderTarget2D>(StaticConstructObject(UTextureRenderTarget2D::StaticClass()));
	RenderTex->AddToRoot();
	RenderTex->ClearColor = FLinearColor(0,0,0,1); //0.2
	RenderTex->bNeedsTwoCopies = false;
	RenderTex->bHDR = false;
	
	//Set pixel format to include alpha			//try 960					//floatRGBA = additive
	RenderTex->InitCustomFormat(Dimensions.X, Dimensions.Y, EPixelFormat::PF_A16B16G16R16 ,  true); //linear gamma
	
	RenderTex->UpdateResourceImmediate();
	
	/*
	//Create New Canvas 
	Canvas = NULL; 
	//Canvas = new FCanvas((FTextureRenderTarget2DResource*) RenderTex->Resource, NULL, 0,0,0);
	Canvas = new FCanvas((FTextureRenderTarget2DResource*) RenderTex->Resource,NULL, GetWorld(), ERHIFeatureLevel::SM4);
	
	Canvas->Clear(RenderTex->ClearColor);
	 */

#Crash

If I uncomment the commented out section where I create the FCanvas, the game crashes with this message, very consistently:

[2014.10.21-21.44.45:359][220]LogWindows: === Critical error: ===
Fatal error: [File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.5\Engine\Source\Runtime\RenderCore\Private\RenderingThread.cpp] [Line: 641] 
Rendering thread exception:
Assertion failed: IsInGameThread() [File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.5\Engine\Source\Runtime\Engine\Private\GlobalShader.cpp] [Line: 341] 



KERNELBASE.dll!UnknownFunction (0x000007fefd089e5d) + 0 bytes [UnknownFile:0]
UE4Editor-Core.dll!UnknownFunction (0x000007fedcd571b4) + 0 bytes [UnknownFile:0]
UE4Editor-Core.dll!UnknownFunction (0x000007fedcbe98b8) + 0 bytes [UnknownFile:0]
UE4Editor-Core.dll!UnknownFunction (0x000007fedcbce882) + 0 bytes [UnknownFile:0]
UE4Editor-Engine.dll!UnknownFunction (0x000007feda63cb4a) + 0 bytes [UnknownFile:0]
UE4Editor-Engine.dll!UnknownFunction (0x000007feda44ae4a) + 0 bytes [UnknownFile:0]
UE4Editor-Engine.dll!UnknownFunction (0x000007feda42a66f) + 0 bytes [UnknownFile:0]
UE4Editor-Engine.dll!UnknownFunction (0x000007fedb0a282b) + 0 bytes [UnknownFile:0]
UE4Editor-Engine.dll!UnknownFunction (0x000007fedb0add62) + 0 bytes [UnknownFile:0]
UE4Editor-Core.dll!UnknownFunction (0x000007fedcb06504) + 0 bytes [UnknownFile:0]
UE4Editor-Core.dll!UnknownFunction (0x000007fedcb0668d) + 0 bytes [UnknownFile:0]
UE4Editor-RenderCore.dll!UnknownFunction (0x000007fede41fc33) + 0 bytes [UnknownFile:0]
UE4Editor-RenderCore.dll!UnknownFunction (0x000007fede4200c9) + 0 bytes [UnknownFile:0]
UE4Editor-Core.dll!UnknownFunction (0x000007fedcd56316) + 0 bytes [UnknownFile:0]
UE4Editor-Core.dll!UnknownFunction (0x000007fedcd4ad3d) + 0 bytes [UnknownFile:0]
kernel32.dll!UnknownFunction (0x000000007704652d) + 0 bytes [UnknownFile:0]
ntdll.dll!UnknownFunction (0x000000007717c521) + 0 bytes [UnknownFile:0]
ntdll.dll!UnknownFunction (0x000000007717c521) + 0 bytes [UnknownFile:0]

#Render Thread?!

Why is it crashing on IsInGameThread() ?!

I am not doing anything fancy at all, the only relevant code and the only code that is crashing the game is what I’ve posted above, and again, it is just the lines that I commented out, the making of the new FCanvas!

#Help

Please help!

I need a way to make an FCanvas and draw to it in 4.5!

#I tried CanvasRenderTarget2D As Well

I tried using James Tan’s CanvasRenderTarget2D as well, and I also got a crash!

The crash is precisely and only on the line where I try to create the CanvasRenderTarget2D using entirely and only the code that is part of the Engine itself:

RenderTex =  
	UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(		//<~~~ Crash is here
		UCanvasRenderTarget2D::StaticClass(), 
		Dimensions.X, Dimensions.Y
	);

#Full Code

void ASolusPDAButtonMesh::InitializeTextureRender(FVector2D IN_Dimensions)
{
	Dimensions = IN_Dimensions;
	
	/*
	RenderTex =  
		UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(	//<~~~ Crash is here
			UCanvasRenderTarget2D::StaticClass(), 
			Dimensions.X, Dimensions.Y
		);
	
	RenderTex->AddToRoot();
	RenderTex->ClearColor = FLinearColor(0,0,0,1); //0.2
	RenderTex->bNeedsTwoCopies = false;
	RenderTex->bHDR = false;
	
	//Set pixel format to include alpha			//try 960					//floatRGBA = additive
	RenderTex->InitCustomFormat(Dimensions.X, Dimensions.Y, EPixelFormat::PF_A16B16G16R16 ,  true); //linear gamma
	
	//Add Binding!
	RenderTex->OnCanvasRenderTargetUpdate.AddDynamic(this, &ASolusPDAButtonMesh::OnCanvasRenderTargetUpdate);
	*/ 

#Crash

[2014.10.21-22.26.26:834][281]LogWindows: === Critical error: ===
Fatal error!

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000188

UE4Editor-Engine.dll!UnknownFunction (0x000007feda4607a9) + 0 bytes [UnknownFile:0]
UE4Editor-Engine.dll!UnknownFunction (0x000007feda41e0d3) + 0 bytes [UnknownFile:0]
UE4Editor-Solus.dll!ASolusPDAButtonMesh::InitializeTextureRender() (0x000007fed106b3a7) + 0 bytes [c:\solus\source\solus\base\soluspdabuttonmesh.cpp:88]
UE4Editor-Solus.dll!ASolusPCSoul::CreatePDAMeshButton() (0x000007fed104e741) + 0 bytes [c:\solus\source\solus\soluspc\soluspcsoul.cpp:268]
UE4Editor-Solus.dll!ASolusPCSleepMenu::SolusSleepMenu_CreatePDAScreenButtons() (0x000007fed10b2a70) + 170 bytes [c:\solus\source\solus\soluspc\soluspcsleepmenu.cpp:90]
UE4Editor-Solus.dll!ASolusPCSleepMenu::SolusSleepMenu_Open() (0x000007fed10b37f5) + 8 bytes [c:\solus\source\solus\soluspc\soluspcsleepmenu.cpp:79]
UE4Editor-CoreUObject.dll!UnknownFunction (0x000007feddf96394) + 0 bytes [UnknownFile:0]

#Help!

I have no way to render to textures from code in 4.5!

Rama

#Cant Upgrade Solus to 4.5

I can’t upgrade Solus until I hear back from you, because I need to render to texture from code in order to render various system son the in-game PDA.

Please do let me know as soon as you can!

Rama

Hi Rama,

So are you creating a texture render target from the game thread?
If yes You should create a render command for the render thread, try something like this:

ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(
			ThisIsMyTestRenderQueueCommand,
			UCanvasRenderTarget2D*,RenderTex,RenderTex,
		{
			RenderTex =  
			 UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(
				 UCanvasRenderTarget2D::StaticClass(), 
				 Dimensions.X, Dimensions.Y
			 );
		});

of course my solution may not work, but it is worth to try;0

Regards

Pierdek

What build.cs addition do I need to use ENQUEUE macro? and what #include?

I tried #include “RenderCore.h” but I still get these linker errors

1>Module.Solus.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static enum ENamedThreads::Type __cdecl FRenderCommand::GetDesiredThread(void)" (__imp_?
1>Module.Solus.cpp.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) class FRHICommandListImmediate & __cdecl GetImmediateCommandList_ForRenderCommand(void)" (__imp_?GetImmediateCommandList_ForRenderCommand@@YAAEAVFRHICommandListImmediate@@XZ) referenced in function "public: void __cdecl `public: void __cdecl ASolusPDAButtonMesh::InitializeTextureRender(struct FVector2D)'::`2'::EURCMacro_PleaseDontCrash::DoTask(enum ENamedThreads::Type,class TRefCountPtr<class FGraphEvent> const &)" (?DoTask@EURCMacro_PleaseDontCrash@?1??InitializeTextureRender@ASolusPDAButtonMesh@@QEAAXUFVector2D@@@Z@QEAAXW4Type@ENamedThreads@@AEBV?$TRefCountPtr@VFGraphEvent@@@@@Z)
1>Module.Solus.cpp.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) bool GIsThreadedRendering" (__imp_?GIsThreadedRendering@@3_NA)
1>Module.Solus.cpp.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) bool GMainThreadBlockedOnRenderThread" (__imp_?GMainThreadBlockedOnRenderThread@@3_NA)

#The Obvious Fact Should Not Be Ignored

The obvious facts here should not be ignored

  • the same code that now crashes the engine worked in 4.3 and 4.4 and during the Beta
  • One of the core engine classes, CanvasRenderTarget2D now crashes the engine when I try to run its very own static creation command, and there’s no indication that this cannot be done inside the game thread. And this code worked in 4.3 and 4.4 and when James Tan created it!

#The Big Question Epic Needs To Answer

What has happened in 4.5 that is causing both FCanvas and CanvasRenderTarget2D to crash?

#Code

This engine code (less than 30 lines) now crashes the game, as does my code above which creates a new FCanvas

What is going on here? This is all happening in 4.5 only!

UCanvasRenderTarget2D* UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(TSubclassOf<UCanvasRenderTarget2D> CanvasRenderTarget2DClass, int32 Width, int32 Height)
{
	if (Width > 0 && Height > 0)
	{
		UCanvasRenderTarget2D* NewCanvasRenderTarget = ConstructObject<UCanvasRenderTarget2D>(CanvasRenderTarget2DClass, GetTransientPackage());
		if (NewCanvasRenderTarget)
		{
			NewCanvasRenderTarget->InitAutoFormat(Width, Height);
			return NewCanvasRenderTarget;
		}
	}

	return nullptr;
}

Hi Rama,

Would you be able to provide some more information to help us reproduce this issue?

  • What base class is ASolusPDAButtonMesh derived from?
  • How and where are you declaring Dimensions, RenderTex, and Canvas?

The crash in CreateCanvasRenderTarget2D comes down to the fact that they changed the way they initialise the FCanvas from 4.4 to 4.5:

FCanvas RenderCanvas( GameThread_GetRenderTargetResource( ), nullptr, FApp::GetCurrentTime( ) - GStartTime, FApp::GetDeltaTime( ), FApp::GetCurrentTime( ) - GStartTime, GetWorld()->FeatureLevel );

Now requiring the Feature Level, the problem here is though that GetWorld( ) returns NULL. I replaced the above line with the below line in CanvasRenderTarget2D.cpp at Line 53 with the following:

FCanvas RenderCanvas( GameThread_GetRenderTargetResource( ), nullptr, FApp::GetCurrentTime( ) - GStartTime, FApp::GetDeltaTime( ), FApp::GetCurrentTime( ) - GStartTime, /* GetWorld()->FeatureLevel */  GetMaxRHIFeatureLevel( ) );

Which stopped the crashing for me. I will continue to test the other issue your having with FCanvas and GameThread vs RenderThread

ASolusPDaButtonMesh is a StaticMeshActor

I running all code in the Game Thread

FVector2D Dimensions is received from input parameter and you could use 512,512 as a test case

so

FVector2D Dimensions(512,512);

RenderTex is in the .h file as either

UPROPERTY()
UCanvasRenderTarget2D* RenderTex;

or

UPROPERTY()
UTextureRenderTarget2D* RenderTex;
	
FCanvas* Canvas;

Depending which version of code you are testing, the FCanvas method or the CanvasRenderTarget2D method

#Repro

Repro should be pretty easy, just have this in your .h of a static mesh extending class

UPROPERTY()
    UTextureRenderTarget2D* RenderTex;
    	
    FCanvas* Canvas;

then cpp:

FVector2D Dimensions(512,512);

RenderTex = CastChecked<UTextureRenderTarget2D>(StaticConstructObject(UTextureRenderTarget2D::StaticClass()));
RenderTex->AddToRoot();
RenderTex->ClearColor = FLinearColor(0,0,0,1); //0.2
RenderTex->bNeedsTwoCopies = false;
RenderTex->bHDR = false;

//Set pixel format to include alpha			//try 960					//floatRGBA = additive
RenderTex->InitCustomFormat(Dimensions.X, Dimensions.Y, EPixelFormat::PF_A16B16G16R16 ,  true); //linear gamma

RenderTex->UpdateResourceImmediate();

//Create New Canvas 
Canvas = NULL; 
Canvas = new FCanvas((FTextureRenderTarget2DResource*) RenderTex->Resource, NULL, 0,0,0);
Canvas->Clear(RenderTex->ClearColor);

Crash happens on the new FCanvas line

all of this in game thread :slight_smile:

Thanks!

Rama

#Alternative Repro for CanvasRenderTarget

If you want to see the crash for the CanvasRenderTarget that’s even simpler!

  • Same static mesh extending class

#.h

UPROPERTY()
UCanvasRenderTarget2D* RenderTex;

#.cpp
RenderTex =
UCanvasRenderTarget2D::CreateCanvasRenderTarget2D(
UCanvasRenderTarget2D::StaticClass(),
512, 512
);

Crash in this case happens on trying to CreateCanvasRenderTarget2D, the only line of code here.

This is all in game thread :slight_smile:

You could trigger this code on key press via Blueprints if you like, I am trigger this code when player presses key to open the Solus Sleep Menu

Thanks!

Rama

#Awesome Work Ehamloptiran!

That’s amazing research and solution finding on your part Ehamloptiran, thank you!

Unfortunately it doesnt help me because Hourences and the rest of the Solus team dont use a Github Engine, so Epic I really need you to fix this,

#What Can I Do With Full Release Only?

Now what I am supposed to do until the first hotfix comes Epic?

The direct impact of this engine-code crash is that I am unable to continue work on Solus in many ways cause we needed 4.5 for UMG and now we can’t upgrade.

Rama

#new FCanvas() crash?

I still very curious why this also crashes the Engine:

Canvas = new FCanvas((FTextureRenderTarget2DResource*) RenderTex->Resource,NULL, GetWorld(), ERHIFeatureLevel::SM4);

Because on the surface this looks like quite a different issue to me. since GetWorld() will be valid in the Static Mesh Actor extending class in which it is being used.

Thanks again for your help Ehamloptiran!

Epic please address this in first Hotfix if you can or else I will be stalled even longer from being able to continue Solus development!

Also if anyone has any idea how I can get around this prior to a hotfix let me know, again I can only use a full release build, so it has to be a project-level solution.

Thanks!

Rama

Hi Rama,

Thank you for providing the exact code to reproduce this issue.

I was able to reproduce the crash related to CanvasRenderTarget2D and have submitted a report for further investigation of that issue (UE-4570). However, I still have not been able to reproduce the crash using TextureRenderTarget2D. Using the code below, I was able to load the project normally.

// .h

UCLASS()
class TESTSOLUS_API AMyStaticMeshActor : public AStaticMeshActor
{
	GENERATED_UCLASS_BODY()

	UPROPERTY()
	UTextureRenderTarget2D* RenderTex;

	FCanvas* Canvas;
};

// .cpp
AMyStaticMeshActor::AMyStaticMeshActor(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{
	FVector2D Dimensions(512, 512);

	RenderTex = CastChecked<UTextureRenderTarget2D>(StaticConstructObject(UTextureRenderTarget2D::StaticClass()));
	RenderTex->AddToRoot();
	RenderTex->ClearColor = FLinearColor(0, 0, 0, 1);
	RenderTex->bNeedsTwoCopies = false;
	RenderTex->bHDR = false;

	RenderTex->InitCustomFormat(Dimensions.X, Dimensions.Y, EPixelFormat::PF_A16B16G16R16, true);
	RenderTex->UpdateResourceImmediate();

	Canvas = NULL;
	//Canvas = new FCanvas((FTextureRenderTarget2DResource*)RenderTex->Resource, NULL, 0, 0, 0);  // Works in 4.4.3, not in 4.5
	Canvas = new FCanvas((FTextureRenderTarget2DResource*)RenderTex->Resource, NULL, GetWorld(), ERHIFeatureLevel::SM4);
	Canvas->Clear(RenderTex->ClearColor);
}

Unless I am missing something, that should be identical to the code you provided to reproduce this crash. Do you see any differences between what you have in your project and what I have here?

Hi there Tim!

Yes in my own tests the crash doesn’t happen immediately, but when I try to do anything else in the normal Solus code base, after running the above code then I get the crash in the global shader!

I know I am not providing the best repro steps here, but I know the crash is being caused by 4.5 and the code above, which worked great in 4.4.

This crash has literally halted development on Solus in terms of anything related to upgrading to 4.5, which is basically everything we have yet to do which is UMG.

Basically my experience goes something like this in Solus 4.5

  • do normal solus things without calling the new FCanvas code, no crash
  • run the code above, and then go back to normal Solus things, reliable crash every time, in the same place, the GlobalShader.cpp line 341.

I have never seen this crash before, and it only occurs in conjunction with the code above!

The code above does not trigger an instant crash, but if I try to do anything else after that then I get the crash!

Again I know this sounds a bit vague, but I really need help with this because it is halting development on Solus until I have a real solution!

The CanvasRenderTarget2D solution could work, but I need a solution as quickly as possible.

Please do have the fix for CanvasRenderTarget2D implemented as quickly as you can, Ehamloptiran already gave you a working solution!

Rama

#This Matter Has Been Resolved

Thank you for your input Tim, it spurned me onward to find the solution!

Please see my response to Ehamloptiran’s answer

Rama

PS: I will submit a pull request to fix the crash in UCanvasRenderTarget2D, I already implemented a solution in a local version of that class

#Solution Found!

Dear Ehamloptiran,

your use of the function GetMaxRHIFeatureLevel( ) is what saved the day for me!

This crashed for me

FileBrowserCanvas = new FCanvas((FTextureRenderTarget2DResource*) FileBrowserRenderTex->Resource,NULL, GetWorld(), ERHIFeatureLevel::SM4 );

this does not

FileBrowserCanvas = new FCanvas((FTextureRenderTarget2DResource*) FileBrowserRenderTex->Resource,NULL, GetWorld(), GetMaxRHIFeatureLevel( ) );

For some reason when I was arbitrarily choosing a feature level this confused UE4, but when I use GetMaxRHIFeatureLevel it works fine!

#Thanks Again Ehamloptiran!

Rama

#Pull Request Submitted

I submitted a pull request for the CanvasRenderTarget2D crash fix here!

This is the solution I used to remove the crash :slight_smile:

https://github.com/EpicGames/UnrealEngine/pull/542/files

#Pull Request Submitted

I submitted a pull request for the CanvasRenderTarget2D crash fix here!

This is the solution I used to remove the crash :slight_smile:

https://github.com/EpicGames/UnrealEngine/pull/542/files