Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/VT/UniquePageList.h
2025-05-18 13:04:45 +08:00

93 lines
1.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "VirtualTextureShared.h"
#include "Containers/HashTable.h"
class FUniquePageList
{
public:
FUniquePageList();
void Initialize();
void Add( uint32 Page, uint32 Count );
uint32 GetNum() const { return NumPages; }
uint32 GetPage( uint32 Index ) const { return Pages[ Index ]; }
uint32 GetCount( uint32 Index ) const { return Counts[ Index ]; }
void MergePages(const FUniquePageList* RESTRICT Other);
private:
enum
{
HashSize = 16*1024,
MaxUniquePages = 8*1024,
};
bool bInitialized;
uint32 NumPages;
uint32 MaxNumCollisions;
uint16 HashIndices[HashSize];
uint32 Pages[ MaxUniquePages ];
uint16 Counts[ MaxUniquePages ];
};
FUniquePageList::FUniquePageList()
: bInitialized( false )
, NumPages( 0 )
, MaxNumCollisions( 0 )
{}
void FUniquePageList::Initialize()
{
if (!bInitialized)
{
FMemory::Memset(HashIndices, 0xff);
bInitialized = true;
}
}
void FUniquePageList::Add( uint32 Page, uint32 Count )
{
uint32 HashIndex = MurmurFinalize32(Page) & (HashSize - 1u);
uint32 NumCollisions = 0u;
while (true)
{
uint32 PageIndex = HashIndices[HashIndex];
if (PageIndex == 0xffff)
{
if (NumPages < MaxUniquePages)
{
PageIndex = NumPages++;
HashIndices[HashIndex] = PageIndex;
Pages[PageIndex] = Page;
Counts[PageIndex] = Count;
}
break;
}
else if (Pages[PageIndex] == Page)
{
const uint32 PrevCount = Counts[PageIndex];
Counts[PageIndex] = FMath::Min<uint32>(PrevCount + Count, 0xffff);
break;
}
HashIndex = (HashIndex + 1u) & (HashSize - 1u);
++NumCollisions;
}
#if DO_GUARD_SLOW
MaxNumCollisions = FMath::Max(MaxNumCollisions, NumCollisions);
#endif // DO_GUARD_SLOW
}
void FUniquePageList::MergePages(const FUniquePageList* RESTRICT Other)
{
for (uint32 Index = 0u; Index < Other->NumPages; ++Index)
{
Add(Other->Pages[Index], Other->Counts[Index]);
}
}