Hi all,
While investigating performance in our game, I found that there was a lot of calls to FRenderTargetPool::CreateRenderTarget.
Tracing further, what seems to be the pattern is that we have a view extension which uses a pooled render target with a dimension that depends on the current rendering resolution.
This, coupled with planar reflection causes that pooled render target to be re-queried via FindFreeElement several time in a frame with different resolution : once for each planar reflection, and once more for the final render.
That behavior makes sense, however, it was unexpected that this would lead to several calls to CreateRenderTarget every frame since it’s supposed to be pooled, and the code led me to believe that render targets allocated in such a way would stick around for up to 2 frames when not used, and at least a frame since things seems to be released only via FRenderTargetPool::TickPoolElements().
However, I don’t understand this part of FRenderTargetPool::FindFreeElement:
bool FRenderTargetPool::FindFreeElement(FRHICommandListBase& RHICmdList, const FRHITextureCreateInfo& Desc, TRefCountPtr<IPooledRenderTarget>& Out, const TCHAR* Name)
{
...
// if we can keep the current one, do that
if (Out)
{
Current = (FPooledRenderTarget*)Out.GetReference();
if (Translate(Out->GetDesc()) == Desc) <--- Ends up being false since the resolution changes
{
}
else
{
// release old reference, it might free a RT we can use
Out = 0;
bFreeCurrent = Current->IsFree(); <--- This causes the RT to be marked as needed to be freed
}
}
...
if (bFreeCurrent)
{
...
FreeElementAtIndex(Index); <--- This will effectively free the RT
}
Out = FindFreeElement(RHICmdList, Desc, Name); <--- No subsequent FindFreeElement will ever match that RT, because FreeElementAtIndex also clears the hash in PooledRenderTargetHashes which would be used to match that RT again in another call
return false;
}
It appears that commenting out “bFreeCurrent = Current->IsFree();” does produce the expected outcome where a RT sticks around for a while, and in the planar reflections cases, the RT do end up being reused in the next frame.
Am I missing something or is it an oversight?
Thank you!
[Attachment Removed]