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
FShaderParameter
because they are not getting bound correctly (even though I’m callingFooParam.Bind(ShaderMap, TEXT("ShaderMap))
. - Using
FShaderUniformBufferParameter
correctly causes the parameter to be bound, but then I cannot useSetShaderValue
becauseFShaderUniformBufferParameter
andFShaderParameter
are unrelated classes. I need to useSetUniformBufferParameter
. - To use
SetUniformBufferParameter
I need to create aFRHIUniformBuffer
by callingRHICreateUniformBuffer
and this is fine…except I just did the same thingTUniformBuffer
is 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?