You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- can be used to track information about a primitive over time without needing to track changes in PackedPrimitiveIndex - will have the same high-water mark to packed index, but will persist for longer, potentially (allocator picks new from the front). - Add PersistentPrimitiveIndex to FPrimitiveSceneData / SceneData.ush, to enable access on the GPU - Add FSpanAllocator, an incremental improvement over FGrowOnlySpanAllocator - which shrinks as well and has efficient allocation of unit-sized allocations. #rb rune.stubbe,Krzysztof.Narkowicz #preflight 61e6b538837b79f7ccdc860f #ROBOMERGE-AUTHOR: ola.olsson #ROBOMERGE-SOURCE: CL 18638699 in //UE5/Release-5.0/... via CL 18638708 via CL 18638715 #ROBOMERGE-BOT: UE5 (Release-Engine-Test -> Main) (v899-18417669) [CL 18638724 by ola olsson in ue5-main branch]
85 lines
2.4 KiB
C++
85 lines
2.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SpanAllocator.h"
|
|
|
|
void FSpanAllocator::Consolidate()
|
|
{
|
|
// Consolidation
|
|
|
|
if (PendingFreeSpans.IsEmpty() && FirstNonEmptySpan == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 1. Sort the Newly free list by span start, the existing free list is already sorted by construction
|
|
PendingFreeSpans.Sort();
|
|
|
|
// alternate free list, used during consolidation to avoid N^2 worst case, retained to avoid re-allocations.
|
|
TArray<FLinearAllocation, TInlineAllocator<10>> FreeSpansTmp;
|
|
FreeSpansTmp.Reset(FreeSpans.Num());
|
|
|
|
int32 PrevEndOffset = INDEX_NONE;
|
|
int32 PendingFreeIndex = 0;
|
|
|
|
// 2. Joint loop and merge over both free list and newly freed and fuse all adjacent, copy into new free list (to avoid compaction)
|
|
for (int32 Index = 0; Index < FreeSpans.Num() || PendingFreeIndex < PendingFreeSpans.Num(); )
|
|
{
|
|
FLinearAllocation Alloc = Index < FreeSpans.Num() ? FreeSpans[Index] : FLinearAllocation{ MAX_int32, 0 };
|
|
// Make sure we don't run out of both somehow...
|
|
check(PendingFreeIndex < PendingFreeSpans.Num() || Alloc.StartOffset < MAX_int32);
|
|
// Consume the next new alloc if it is before the next old one
|
|
if (PendingFreeIndex < PendingFreeSpans.Num() && PendingFreeSpans[PendingFreeIndex].StartOffset < Alloc.StartOffset)
|
|
{
|
|
Alloc = PendingFreeSpans[PendingFreeIndex++];
|
|
}
|
|
else
|
|
{
|
|
// Otherwise advance the old allocs
|
|
++Index;
|
|
}
|
|
check(Alloc.StartOffset < MAX_int32);
|
|
|
|
// Discard empty allocs
|
|
if (Alloc.Num > 0)
|
|
{
|
|
// Continues the previous one, fuse
|
|
if (PrevEndOffset == Alloc.StartOffset)
|
|
{
|
|
FreeSpansTmp.Last().Num += Alloc.Num;
|
|
}
|
|
else
|
|
{
|
|
FreeSpansTmp.Add(Alloc);
|
|
}
|
|
PrevEndOffset = FreeSpansTmp.Last().Num + FreeSpansTmp.Last().StartOffset;
|
|
}
|
|
}
|
|
|
|
// Trim last span
|
|
if (!FreeSpansTmp.IsEmpty() && FreeSpansTmp.Last().StartOffset + FreeSpansTmp.Last().Num == MaxSize)
|
|
{
|
|
MaxSize -= FreeSpansTmp.Last().Num;
|
|
FreeSpansTmp.Pop(false);
|
|
}
|
|
|
|
// 3. Store new free list
|
|
FreeSpans = MoveTemp(FreeSpansTmp);
|
|
PendingFreeSpans.Empty(PendingFreeSpans.Num());
|
|
FirstNonEmptySpan = 0;
|
|
}
|
|
|
|
int32 FSpanAllocator::SearchFreeList(int32 Num, int32 SearchStartIndex)
|
|
{
|
|
// Search free list for first matching
|
|
for (int32 Index = SearchStartIndex; Index < FreeSpans.Num(); Index++)
|
|
{
|
|
FLinearAllocation CurrentSpan = FreeSpans[Index];
|
|
|
|
if (CurrentSpan.Num >= Num)
|
|
{
|
|
return Index;
|
|
}
|
|
}
|
|
|
|
return INDEX_NONE;
|
|
} |