How To Convert An FRDGTexture into something that can be used by a Material Expression? It can only take UTextures?

Unfortunately render graph/legacy UTexture resources aren’t designed to be dynamically created or resized on the render thread. You had the right idea with copying the shader output to an externally bound render target and then using a texture input node in a Material blueprint to get the texture on the screen. (You might have to do some wizardry to get the render target to wrap correctly on whatever mesh you’re using, but that’s down the road a little bit.)

I’m using a WorldSubsystem derived class to register a SceneViewExtension which dispatches my compute shader pass. The subsystem and its UPROPERTY fields are conveniently accessible from both the SVE and Blueprint. In the view extension, after AddPass(), I have the shader output in a FRDGTextureRef (which you could probably manage depending on how you configure your shader params). Then, I can get a reference to the render target from the subsystem, drill down into its underlying RHI resource (SubsystemTarget->GetRenderTargetResource()), convert that into an RDG reference via pooled render target with GraphBuilder.RegisterExternalTexture(), and finally copy the actual texture with AddCopyTexturePass().

One thing you have to be careful of is to validate the pixel format and screen extent information between your shader output and your render target resource. Specifically, if the pixel format doesn’t match, you’ll get a really obscure crash. The nastiest part about this is having to create and manage the render target on the blueprint side (i.e. on the game thread), requiring that you expose screen dimensions from your view extension out to blueprint and do your render target creation/resizing there. There’s probably a better way to get “primary viewport” extent info in Blueprint or the subsystem, but I haven’t bothered. I can’t post code here, but please ask if you need help.