D3D12 UniformBuffer Read After Free When FastGeo Is Enabled

Hey,

So recently we enabled FastGeoStreaming and I’ve observed a crash when changing `r.MaterialQualityLevel` during the depth pre-pass, in a cooked build.

It occurs in ValidateUniformBuffer (does not occur when the plugin is disabled).

inline void ValidateBoundUniformBuffer(FD3D12UniformBuffer* InUniformBuffer, FRHIShader* InShaderRHI, uint32 InBufferIndex)
{
#if DO_CHECK
	auto const& LayoutHashes = InShaderRHI->GetShaderResourceTable().ResourceTableLayoutHashes;

	if (InBufferIndex < (uint32)LayoutHashes.Num())
	{
		uint32 UniformBufferHash = InUniformBuffer->GetLayout().GetHash(); <-------------- here
		uint32 ShaderTableHash = LayoutHashes[InBufferIndex];
		ensureMsgf(ShaderTableHash == 0 || UniformBufferHash == ShaderTableHash,
			TEXT("Invalid uniform buffer %s bound on %sShader at index %d."),
			*(InUniformBuffer->GetLayout().GetDebugName()),
			GetShaderFrequencyString(InShaderRHI->GetFrequency(), false),
			InBufferIndex);
	}
#endif
}

The UB in question is the materials `Material` uniform buffer and is effectively pointing at the UB from before the quality level changed, which was since freed during:

FMaterialRenderProxy::InvalidateUniformExpressionCache(bool bRecreateUniformBuffer)

But re-allocated in:

FMaterialRenderProxy::EvaluateUniformExpressions(FRHICommandListBase& RHICmdList, FUniformExpressionCache& OutUniformExpressionCache, const FMaterialRenderContext& Context, FUniformExpressionCacheAsyncUpdater* Updater) const

I added some sketchy logging around `FMaterialShader::GetShaderBindings` to keep track of what pointer was currently stashed in `UniformExpressionCache.UniformBuffer`, using the callstack up until `FScene::Update()` as a way to book keep it and each pass appeared to have the most up to date uniform buffer pointer.

I was wondering if you had ever encountered something like this before / had tips on debugging it further?

Many thanks,

Alister

After testing, this happens on vanilla Lyra.

Enable FastGeoStreaming, add the FastGeo transformer in the world setting (L_Expanse was what I testing on).

After changing material quality level (might need to move around a bit) and it crashes in basically the same way.

Hello!

Thanks for reporting this issue. I was able to reproduce the crash in a cooked build (not in PIE) and created the following internal issue which should be visible soon Unreal Engine Issues and Bug Tracker (UE\-318822\).

This issue was also reported in this ticket [Content removed] however we didn’t have a repro case or details for a workaround.