My team and I are porting few D3D11 custom shaders to RHI.
The shaders make use of constant buffers (cbuffer) which in the RHI world
are called uniform buffers. We got it working using TUniformBuffer but
the performance was not optimal. The reason is that we need to update them
multiple times per frame and we naively went with TUniformBuffer::SetContents
which should update the buffers…except it does not - it destroys them and
recreates a new one with the updated data and this is slow.
I attempted some workarounds:
- I cannot store the buffers as
FShaderParameterbecause they are not getting bound correctly (even though I’m callingFooParam.Bind(ShaderMap, TEXT("ShaderMap)). - Using
FShaderUniformBufferParametercorrectly causes the parameter to be bound, but then I cannot useSetShaderValuebecauseFShaderUniformBufferParameterandFShaderParameterare unrelated classes. I need to useSetUniformBufferParameter. - To use
SetUniformBufferParameterI need to create aFRHIUniformBufferby callingRHICreateUniformBufferand this is fine…except I just did the same thingTUniformBufferis doing internally.
The problem is that unlike all other data objects (vertex, index and structured buffers, textures)
there’s neither RHIUpdateUniformBuffer, nor RHILockUniformBuffer.
After some digging around the codebase I found that the engine uses cbuffers in only a few places, none
of which requires frequent updates…except some D3D-related slate magic which actually defines
its own FSlateD3DConstantBuffer for the sole purpose of updating the constant buffer without
recreating it!
So, am I missing something or is there a performant way to update a uniform buffer?