Assign texture referenced by FTexture2DRHIRef directly in Material Instance Dynamic?


I am interested in learning about compute shaders and using them in UE4, and so I’m looking at this example project I found here.
I have looked also at using compute shaders in Unity, so I know some basics already.

Now, in the example the compute shader writes to an RWTexture2D, which is bound to an FTexture2DRHIRef through an FUnorderedAccessViewRHIRef.

FRHIResourceCreateInfo CreateInfo;
FTexture2DRHIRef Texture = RHICreateTexture2D(SizeX, SizeY, PF_R32_UINT, 1, 1,
                             TexCreate_ShaderResource | TexCreate_UAV, CreateInfo);
FUnorderedAccessViewRHIRef TextureUAV = RHICreateUnorderedAccessView(Texture);

/* Set inputs/outputs and dispatch compute shader */
ComputeShader->SetSurfaces(RHICmdList, TextureUAV);
ComputeShader->SetUniformBuffers(RHICmdList, ConstantParameters, VariableParameters);
DispatchComputeShader(RHICmdList, *ComputeShader, n, n, 1);

The example then uses the FTexture2DRHIRef as input to a PixelShader, which renders to a UTextureRenderTarget2D, which is then assigned to the parameter of the dynamic material instance.

My problem:
I am interested in modifying an existing texture in a compute shader, without necessarily needing a pixel shader. So I would like to directly use the texture referenced by the FTexture2DRHIRef in a dynamic material instance. Without going through more shaders or having to take the texture through the CPU. But there is just so much to the RHI side of the engine, which I’m quite new to, I haven’t been able to figure this out.

(On a side note, in future I’d also like to modify existing meshes in compute shaders (not adding/removing verts, but changing their position and normals at least). But I fear this will be even harder to find out if/how that is possible, so I’m focusing on the texture problem for now :wink: )

have you ever been able to solve this?

Nope. I didn’t want to spend too much time so I used a different approach (do the work on the cpu and use a render command to update the texture). Worked well enough for me at the time, although it would be cool to modify data directly on the gpu. I’m a bit worried that that would require using/modifying specific render api code (e.g. DX) and I didn’t want to go that far. Also I don’t know if anything changed in newer version of UE to make this easier. I think I saw something about making writing shaders a bit more convenient, but I didn’t check it out.

Have a look at UTexture2DDynamic class in the engine source code. It has a simple implementation. Create your own texture class (derived from UTexture) similar to UTexture2DDynamic implementation and pass in the RHI reference to your texture uobject on initialization. I ran into a similar problem and this method works for me. Your UTexture implementation can now be set as a parameter to the MaterialInstanceDynamic

Thanks for this; I wasn’t really expecting anything anymore (actually I forgot about the question). I’ll try to find some time to give it a try soon (I hope) and get back. Need to dig around a bit, and I’m having multiple deadlines to deal with right now, but I’ll try to remember :slight_smile:

You manage the RHI from the resource object. Similar to the FTexture2DDynamicResource, you’ll create your own resource object, then override the init and release functions. Create this resource instance in the CreateResource() function

In the init function of the resource object, you’ll probably not create a new texture RHI but reuse the existing one you passed when creating the uobject.

I intend to do the same. So when I implement a custom UTexture class, what do I do with the RHI reference after passing it to the Init/Create methods? I’ve looked at the source for UTexture2DDynamic, but couldn’t find anything.