USkyLightComponent::SetIntensity is very slow

To be able to create a day-night cycle I need to change the skylight intensity at runtime. The problem is that at the moment changing the skylight intensity costs ~5ms ! This is the code involved (UE 4.6.1):

/** Set brightness of the light */
void USkyLightComponent::SetIntensity(float NewIntensity)
{
	// Can't set brightness on a static light
	if (!(IsRegistered() && Mobility == EComponentMobility::Static)
		&& Intensity != NewIntensity)
	{
		Intensity = NewIntensity;
		MarkRenderStateDirty();
	}
}

What happen calling USkyLightComponent::MarkRenderStateDirty ?

→ USkyLightComponent::DestroyRenderState_Concurrent
→ USkyLightComponent::CreateRenderState_Concurrent
→ FScene::SetSkyLight (bScenesPrimitivesNeedStaticMeshElementUpdate became TRUE)
→ […the frame after]
→ FScene::ConditionalMarkStaticMeshElementsForUpdate() and here:

for (int32 PrimitiveIndex = 0; PrimitiveIndex < Primitives.Num(); PrimitiveIndex++)
{
    Primitives[PrimitiveIndex]->BeginDeferredUpdateStaticMeshes();
}

is very heavy!

From my tests is not need to call MarkRenderStateDirty in that case but just:

/** Set brightness of the light */
void USkyLightComponent::SetIntensity(float NewIntensity)
{
	// Can't set brightness on a static light
	if (!(IsRegistered() && Mobility == EComponentMobility::Static)
		&& Intensity != NewIntensity)
	{
		Intensity = NewIntensity;
		if (SceneProxy != nullptr)
			SceneProxy->LightColor = FLinearColor(LightColor) * Intensity;
	}
}

It works fine without any overhead.
I can create a patch in github if this make sense…

thanks,
Martin

Hi Martin,

The engine re-creates the rendering state for a reason. SceneProxies are owned by the Rendering Thread, so you should never touch them directly from the Game Thread. I see your point though. I would also like to know if there’s any way to update the scene proxy without re-creating it. Any devs here who can comment on that?

~Robert.

I wonder if ENQUEUE_UNIQUE_RENDER_COMMAND can be used to update data in scene proxies?