[4.7] DrawItem Crashes on GetD3D11TextureFromRHITexture

I’ve been working on a HUD in Canvas and in the process of refactoring I ran into a bit of an issue with FCanvasTileItem. I’ve written a helper function which generates a FCanvasTileItem and then Draws it to the canvas.

USTRUCT()
struct FCGWidgetBrush
{
	GENERATED_USTRUCT_BODY()

	/** The actual texture for this "brush". */
	UPROPERTY(EditDefaultsOnly, Category = Texture)
	UTexture* Texture;

	/**UV start Point.*/
	UPROPERTY(EditDefaultsOnly, Category = Texture)
	FVector2D UV;

	/** Texture size in relation to UV coordinates */
	UPROPERTY(EditDefaultsOnly, Category = Texture)
	FVector2D UVSize;
	
	/** The Scale of the icon, not normalized.*/
	UPROPERTY(EditDefaultsOnly, Category = Texture)
	FVector2D Scale;

	/** The anchor point of the texture. */
	UPROPERTY(EditDefaultsOnly, Category = Texture)
	FVector2D Anchor;
	
	/** The alignment of the texture relative to the Anchor. Normalized*/
	UPROPERTY(EditDefaultsOnly, Category = Texture)
	FVector2D Alignment;

	/** The color of this element.*/
	UPROPERTY(EditDefaultsOnly, Category = Texture)
	FLinearColor DefaultColor;
   
	FCGWidgetBrush()
	{
		Scale = FVector2D(1.f, 1.f);
		Anchor = FVector2D(0.f, 0.f);
		Alignment = FVector2D(0.f, 0.f);
		DefaultColor = FLinearColor::White;
	}

};


void UCGHUDWidget::DrawBrush(const FCGWidgetBrush& Brush, const FLinearColor& Color) const
{
	if (Brush.Texture && Brush.Texture->Resource)
	{
		// Scale
		FVector2D Size(UIScale.X * Brush.Scale.X * Brush.UVSize.X, 
			UIScale.Y * Brush.Scale.Y * Brush.UVSize.Y);

		// Anchor Offset
		FVector2D Position(Origin + (Brush.Anchor * UIScale));

		// Alignment - Depends on anchor/origin and alignment.
		Position += Size * Brush.Alignment;

		FCanvasTileItem BrushItem(	Position, Brush.Texture->Resource, 
			Brush.UV, Brush.UVSize + Brush.UV, Color);
		BrushItem.BlendMode = SE_BLEND_Translucent;
		OwnerCanvas->DrawItem(BrushItem);
	}
}

This code executes fine, but I crash in FCanvasBatchedElementRenderItem::Render_GameThread on line 391 in the Canvas.cpp file in Debug Mode. Alternatively, in development I crash with the following crash report:

Access violation - code c0000005
(first/second chance not available)

UE4Editor_D3D11RHI!GetD3D11TextureFromRHITexture()

  • 21 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\windows\d3d11rhi\public\d3d11resources.h:530]
    UE4Editor_D3D11RHI!FD3D11DynamicRHI::RHISetShaderTexture()
  • 46 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\windows\d3d11rhi\private\d3d11commands.cpp:351]
    UE4Editor_Engine!FSimpleElementPS::SetParameters()
  • 127 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\simpleelementshaders.cpp:90]
    UE4Editor_Engine!FSimpleElementGammaBasePS::SetParameters()
  • 32 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\simpleelementshaders.cpp:123]
    UE4Editor_Engine!FBatchedElements::PrepareShaders()
  • 2365 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\batchedelements.cpp:618]
    UE4Editor_Engine!FBatchedElements::Draw()
  • 35479 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\batchedelements.cpp:981]
    UE4Editor_Engine!FCanvasBatchedElementRenderItem::Render_GameThread'::8’::EURCMacro_BatchedDrawCommand::DoTask()
  • 201 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\engine\private\userinterface\canvas.cpp:445]
    UE4Editor_Engine!TGraphTask<FCanvasBatchedElementRenderItem::Render_GameThread'::8’::EURCMacro_BatchedDrawCommand>::ExecuteTask()
  • 456 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\core\public\async\taskgraphinterfaces.h:669]
    UE4Editor_Core!FTaskThread::ProcessTasks()
  • 3125 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\core\private\async\taskgraph.cpp:428]
    UE4Editor_Core!FTaskThread::ProcessTasksUntilQuit()
  • 77 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\core\private\async\taskgraph.cpp:271]
    UE4Editor_RenderCore!RenderingThreadMain()
  • 183 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\rendercore\private\renderingthread.cpp:282]
    UE4Editor_RenderCore!FRenderingThread::Run()
  • 58 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\rendercore\private\renderingthread.cpp:385]
    UE4Editor_Core!FRunnableThreadWin::Run()
  • 102 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\core\private\windows\windowsrunnablethread.cpp:73]
    UE4Editor_Core!FRunnableThreadWin::GuardedRun() + 93 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.7\engine\source\runtime\core\private\windows\windowsrunnablethread.cpp:26]
    kernel32 + 5074 bytes ntdll + 87108
    bytes

To verify that my texture was valid I used the DrawTile function in Canvas which works, am I just neglecting to account for something in regards to FCanvasTileItem?

DrawTile code is as follows:

OwnerCanvas->SetDrawColor(Color);

OwnerCanvas->DrawTile(
Brush.Texture,
Position.X, Position.Y,
Size.X, Size.Y,
Brush.UV.X, Brush.UV.Y,
Brush.UVSize.X, Brush.UVSize.Y,
EBlendMode::BLEND_Translucent);	

Edit:
This code exists in a class which is given the Canvas each DrawHUD call.

I realized that my UV coordinates were not Normalized, and I updated them accordingly. Now the Development Call Stack resembles the Debug one.

The UV Normalization Seems to have resolved my issue, the DrawBrush function now looks like this:

void UCGHUDWidget::DrawBrush(const FCGWidgetBrush& Brush, const FLinearColor& Color, float Rotation) const
{
	if (Brush.Texture && Brush.Texture->Resource)
	{
		// Scale
		FVector2D Size(UIScale.X * Brush.Scale.X * Brush.UL,
			UIScale.Y * Brush.Scale.Y * Brush.VL);

		// Anchor Offset
		FVector2D Position(Origin  + (Brush.Anchor * UIScale));

		// Alignment - Depends on anchor/origin and alignment.
		Position += Size * Brush.Alignment;


		float U = Brush.U / Brush.Texture->Resource->GetSizeX();
		float V = Brush.V / Brush.Texture->Resource->GetSizeY();
		float UL = U + (Brush.UL / Brush.Texture->Resource->GetSizeX());
		float VL = V + (Brush.VL / Brush.Texture->Resource->GetSizeY());
		
		FCanvasTileItem BrushItem(Position, Brush.Texture->Resource, 
			Size, FVector2D(U,V), FVector2D(UL,VL), Color);

		BrushItem.Rotation = FRotator(0, Rotation, 0);
		BrushItem.PivotPoint = Brush.Pivot;
		BrushItem.BlendMode = SE_BLEND_Translucent;

		OwnerCanvas->DrawItem(BrushItem);
	}
}