MaterialQualityLevel 0 (or 2) stalls 4.22

Setting MaterialQualityLevel to 0 or 2 crashes (permanently stalls) 4.22 (setting it to 1 has no effect). We only have one material affected by the material quality switch, on medium and high settings this material uses parallax occlusion mapping, and on low it does not. Multiple material instances have this material as their parent. An image of the material graph should be below.

EDIT: Removing the quality settings node from the material graph does not stop the crash from happening. When changed in the editor UE4 stalls for 30 to 60 seconds and then starts recompiling the materials. Again this did not occur in previous versions of the UE4

EDIT 2 After allowing the materials to recompile the editor now crashes fully. The error reporting dialogue states the issue occurs on Line 2039 in the file \Build++UE4\Sync\Engine\Source\Runtime\Engine\Private\Materials\MaterialShared.cpp

This issue was not present in previous versions on the engine.

The project has been recently upgraded to 4.22 from 4.20, a new project was created and content was migrated across, it was not converted in place.

Computer Specs:

-CPU: Intel(R) Core™ i7-5820K CPU @ 3.30GHz, 3301 Mhz, 6 Core(s), 12 Logical Processor(s)
-GPU: NVIDIA Geforce GTX 1080 Founders Edition
-RAM: 16GB DDR4
-MOTHERBOARD: MSI-7885
-OS: Windows 10 (10.0.17134 Build 17134)

Hello,

We’ve recently made a switch to a new bug reporting method using a more structured form. Please visit the link below for more details and report the issue using the new Bug Submission Form. Feel free to continue to use this thread for community discussion around the issue.

https://epicsupport.force.com/unrealengine/s/

Thanks

Thanks Jeff, I’m afraid however that the bug reporting form won’t submit, it appears to get stuck behind a loading symbol.

So the error appears to be occurring in the function FMaterialRenderProxy::EvaluateUniformExpressions in the MaterialShared.cpp.

In UE 4.20 the function contains this line:

// Create and cache the material's uniform buffer.
	OutUniformExpressionCache.UniformBuffer = UniformExpressionSet.CreateUniformBuffer(Context, CommandListIfLocalMode, &OutUniformExpressionCache.LocalUniformBuffer);

And in UE 4.22 that line has been replaced with:

const FShaderParametersMetadata& UniformBufferStruct = UniformExpressionSet.GetUniformBufferStruct();
FMemMark Mark(FMemStack::Get());
void* TempBuffer = FMemStack::Get().PushBytes(UniformBufferStruct.GetSize(), SHADER_PARAMETER_STRUCT_ALIGNMENT);
UniformExpressionSet.FillUniformBuffer(Context, TempBuffer);
if (CommandListIfLocalMode)
{
	OutUniformExpressionCache.LocalUniformBuffer = CommandListIfLocalMode->BuildLocalUniformBuffer(TempBuffer, UniformBufferStruct.GetSize(), UniformBufferStruct.GetLayout());
	check(OutUniformExpressionCache.LocalUniformBuffer.IsValid());
}
else
{
	if (IsValidRef(OutUniformExpressionCache.UniformBuffer))
	{
		check(OutUniformExpressionCache.UniformBuffer->GetLayout() == UniformBufferStruct.GetLayout());
		RHIUpdateUniformBuffer(OutUniformExpressionCache.UniformBuffer, TempBuffer);
	}
	else
	{
		OutUniformExpressionCache.UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct.GetLayout(), UniformBuffer_MultiFrame);
	}
}

The line check(OutUniformExpressionCache.UniformBuffer->GetLayout() == UniformBufferStruct.GetLayout()); is where the error dialogue states the error occurs. Other than the line in 4.20 being changed to the code from 4.22 the rest of the function is unchanged.
Unfortunately I am not familiar enough with UE4’s source to really understand what has been changed and why.

Removing the Parallax Occlusion Mapping node from the material stops the crash from occurring, so the issue seems to be when the effects changing from high, medium and low material quality settings has on parallax occlusion mapping.
EDIT specifically the issue seems to be when switching from low material quality to medium or high.

Since the both the

check(OutUniformExpressionCache.UniformBuffer->GetLayout() == UniformBufferStruct.GetLayout());
RHIUpdateUniformBuffer(OutUniformExpressionCache.UniformBuffer, TempBuffer);

functions cause the engine to crash I’m assuming the (IsValidRef(OutUniformExpressionCache.UniformBuffer)) If check is returning TRUE when it should be returning FALSE. But forcing it down the FALSE (else) statement so that only

OutUniformExpressionCache.UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct.GetLayout(), UniformBuffer_MultiFrame);

is called, the crash does not occur. My edited version of the function is below:

void FMaterialRenderProxy::EvaluateUniformExpressions(FUniformExpressionCache& OutUniformExpressionCache, const FMaterialRenderContext& Context, FRHICommandList* CommandListIfLocalMode) const
{
	check(IsInParallelRenderingThread());

	SCOPE_CYCLE_COUNTER(STAT_CacheUniformExpressions);
	
	// Retrieve the material's uniform expression set.
	const FUniformExpressionSet& UniformExpressionSet = Context.Material.GetRenderingThreadShaderMap()->GetUniformExpressionSet();

	OutUniformExpressionCache.CachedUniformExpressionShaderMap = Context.Material.GetRenderingThreadShaderMap();

	const FShaderParametersMetadata& UniformBufferStruct = UniformExpressionSet.GetUniformBufferStruct();
	FMemMark Mark(FMemStack::Get());
	void* TempBuffer = FMemStack::Get().PushBytes(UniformBufferStruct.GetSize(), SHADER_PARAMETER_STRUCT_ALIGNMENT);

	UniformExpressionSet.FillUniformBuffer(Context, TempBuffer);

	if (CommandListIfLocalMode)
	{
		OutUniformExpressionCache.LocalUniformBuffer = CommandListIfLocalMode->BuildLocalUniformBuffer(TempBuffer, UniformBufferStruct.GetSize(), UniformBufferStruct.GetLayout());
		check(OutUniformExpressionCache.LocalUniformBuffer.IsValid());
	}
	else
	{
		OutUniformExpressionCache.UniformBuffer = RHICreateUniformBuffer(TempBuffer, UniformBufferStruct.GetLayout(), UniformBuffer_MultiFrame);
	}

	OutUniformExpressionCache.ParameterCollections = UniformExpressionSet.ParameterCollections;

	OutUniformExpressionCache.bUpToDate = true;	
	
}

With this edit a recompile of the editor / engine the crash does not occur.