void FIndirectLightingCache::UpdateCachePrimitive(
	FScene* Scene, 
	FPrimitiveSceneInfo* PrimitiveSceneInfo,
	bool bAllowUnbuiltPreview,
	bool bOpaqueRelevance, 
	TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate,
	TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate)
{
	FPrimitiveSceneProxy* PrimitiveSceneProxy = PrimitiveSceneInfo->Proxy;
	FIndirectLightingCacheAllocation** PrimitiveAllocationPtr = PrimitiveAllocations.Find(PrimitiveSceneInfo->PrimitiveComponentId);
	FIndirectLightingCacheAllocation* PrimitiveAllocation = PrimitiveAllocationPtr != NULL ? *PrimitiveAllocationPtr : NULL;

	if (PrimitiveSceneProxy->WillEverBeLit()
		&& ((bAllowUnbuiltPreview && PrimitiveSceneProxy->HasStaticLighting() && PrimitiveAllocation && PrimitiveAllocation->bIsDirty)
		|| (PrimitiveSceneProxy->IsMovable() && PrimitiveSceneProxy->GetIndirectLightingCacheQuality() != ILCQ_Off)))
	{
		const FIndirectLightingCacheAllocation* AttachmentParentAllocation = NULL;

		if (PrimitiveSceneInfo->LightingAttachmentRoot.IsValid())
		{
			FAttachmentGroupSceneInfo& AttachmentGroup = Scene->AttachmentGroups.FindChecked(PrimitiveSceneInfo->LightingAttachmentRoot);

			if (AttachmentGroup.ParentSceneInfo && AttachmentGroup.ParentSceneInfo->Proxy->LightAttachmentsAsGroup())
			{
				AttachmentParentAllocation = FindPrimitiveAllocation(AttachmentGroup.ParentSceneInfo->PrimitiveComponentId);
			}
		}

		if (AttachmentParentAllocation)
		{
			// Reuse the attachment parent's lighting allocation if part of an attachment group
			PrimitiveSceneInfo->IndirectLightingCacheAllocation = AttachmentParentAllocation;
		}
		else 
		{
			FIndirectLightingCacheAllocation* OriginalAllocation = PrimitiveAllocation;
			const bool bUnbuiltPreview = bAllowUnbuiltPreview && !PrimitiveSceneProxy->IsMovable();
			const bool bPointSample = PrimitiveSceneProxy->GetIndirectLightingCacheQuality() == ILCQ_Point || bUnbuiltPreview || !bOpaqueRelevance;
			const int32 BlockSize = bPointSample ? 1 : GLightingCacheMovableObjectAllocationSize;

			// Light with the cumulative bounds of the entire attachment group
			UpdateCacheAllocation(PrimitiveSceneInfo->GetAttachmentGroupBounds(), BlockSize, bPointSample, PrimitiveAllocation, BlocksToUpdate, TransitionsOverTimeToUpdate);

			// Cache the primitive allocation pointer on the FPrimitiveSceneInfo for base pass rendering
			PrimitiveSceneInfo->IndirectLightingCacheAllocation = PrimitiveAllocation;

			if (OriginalAllocation != PrimitiveAllocation)
			{
				if (OriginalAllocation)
				{
					PrimitiveAllocations.Remove(PrimitiveSceneInfo->PrimitiveComponentId);
				}

				// Allocate space in the atlas for this primitive and add it to a map, whose key is the component, so the allocation will persist through a re-register
				PrimitiveAllocations.Add(PrimitiveSceneInfo->PrimitiveComponentId, PrimitiveAllocation);
			}
		}
	}
}
void FIndirectLightingCache::UpdateTranslucentVolumeCache(FViewInfo& View, TMap<FIntVector, FBlockUpdateInfo>& BlocksToUpdate, TArray<FIndirectLightingCacheAllocation*>& TransitionsOverTimeToUpdate)
{
	extern int32 GUseIndirectLightingCacheInLightingVolume;

	if (View.State && GUseIndirectLightingCacheInLightingVolume)
	{
		FSceneViewState* ViewState = (FSceneViewState*)View.State;

		for (int32 CascadeIndex = 0; CascadeIndex < ARRAY_COUNT(ViewState->TranslucencyLightingCacheAllocations); CascadeIndex++)
		{
			FIndirectLightingCacheAllocation*& Allocation = ViewState->TranslucencyLightingCacheAllocations[CascadeIndex];
			const FBoxSphereBounds Bounds(FBox(View.TranslucencyLightingVolumeMin[CascadeIndex], View.TranslucencyLightingVolumeMin[CascadeIndex] + View.TranslucencyLightingVolumeSize[CascadeIndex]));

			UpdateCacheAllocation(Bounds, GTranslucencyLightingVolumeDim / 4, true, Allocation, BlocksToUpdate, TransitionsOverTimeToUpdate);
		}
	}
}