Material instance's render proxy resources go missing?

I have this material created in editor, and intended to load and draw it to a render target in c++ code. However when running the UKismetRenderingLibrary::DrawMaterialToRenderTarget() function in component’s tick function, it is highly like that FMaterialInstanceResource* Resources[3] array within the material instance contains null pointers or 0x0000FFFF alike pointer values, which, I doubt, coule be garbage collected somewhere or sometime in the process.

Here’s code exempts.

// component constructor
    PrimaryComponentTick.bCanEverTick = true;
    PrimaryComponentTick.TickGroup = TG_PostPhysics;

    static ConstructorHelpers::FObjectFinder<UMaterial> MaterialFinder(TEXT("Material'/MyProject/Materials/RelatedMat.RelatedMat'"));
    if (MaterialFinder.Succeeded())
    {
        RelatedMat = MaterialFinder.Object;
    }
    RelatedMatIns = UMaterialInstanceDynamic::Create(RelatedMat, this, TEXT("RelatedMatIns"));


// component initialization
    ResultRenderTarget = UKismetRenderingLibrary::CreateRenderTarget2D(this, Resolution.X, Resolution.Y, ETextureRenderTargetFormat::RTF_RGBA8);
    ResultRenderTarget->TargetGamma = 2.2f;
    RelatedMatIns->SetScalarParameterValue("TexSize", Resolution.X);
    RelatedMatIns->SetTextureParameterValue("Tex0", RenderTargets[0]);
    RelatedMatIns->SetTextureParameterValue("Tex1", RenderTargets[1]);
    RelatedMatIns->SetTextureParameterValue("Tex2", RenderTargets[2]);
    RelatedMatIns->SetTextureParameterValue("Tex3", RenderTargets[3]);
    RelatedMatIns->SetTextureParameterValue("Tex4", RenderTargets[4]);


// component tick function
    UKismetRenderingLibrary::DrawMaterialToRenderTarget(GetWorld(), ResultRenderTarget, RelatedMatIns); // this is where things go wrong

    FTextureRenderTargetResource* RTResource = FisheyeRenderTarget->GameThread_GetRenderTargetResource();

    FReadSurfaceDataFlags ReadPixelFlags(RCM_MinMax);
		TArray<FColor> pixelBuffer;
        if (FisheyeRTResource->ReadPixels(pixelBuffer, ReadPixelFlags))
        .................

So my question is why material instance’s rendering resources go missing, and how do I prevent this?


Update:
In UCanvas::K2_DrawMaterial(), a FCanvasTitleItem will be created, and during its creation, a check will be executed on InMaterialRenderProxy. When RelatedMatIns contains a illegible resources and send in such value, the program crashes.

Hi ,

代码中“RenderTargets”数组是如何赋值/创建的?

RenderTargets is declared as this:

    UPROPERTY(EditAnywhere, Category = "...")
        TArray<UTextureRenderTarget2D *> RenderTargets;

Later it is initialized as:

if (RenderTargets.Num() > 0)
{
    RenderTargets.Empty();
}
for( /* loop a certain times*/ ):
         auto pRenderTarget = UKismetRenderingLibrary::CreateRenderTarget2D(this, Resolution.X, Resolution.Y, ETextureRenderTargetFormat::RTF_RGBA8);
        pRenderTarget->TargetGamma = 2.2f;
        RenderTargets.Add(pRenderTarget);

你的RelatedMatIns复制后如何保存?RelatedMatIns也是UProperty吗?
你可以尝试给RelatedMatIns赋值后,增加一句:
ReleatedMatIns->AddToRoot();
防止材质本身被垃圾回收,然后看下还是否会崩溃。

可以使用RemoveFromRoot把ReleatedMatIns从Root移除,这样就会被GC。关于GC和UProperty,可以参考官方文档:https://docs.unrealengine.com/en-US/Programming/UnrealArchitecture/Objects/Optimizations中Automatic Updating of References这一段:

If you want an Object pointer that is not a UProperty, consider using TWeakObjectPtr. This is a “weak” pointer, meaning it will not prevent garbage collection, but it can be queried for validity before being accessed and will be set to null if the Object it points to is destroyed.

RelatedMatIns is just a private member of the component.
I’ll try add to root first to see if there’s any effect. Thanks.