UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SimpleStreamableAssetManager.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4#include "CoreMinimal.h"
6#include "Misc/SpinLock.h"
8
11
13struct FBoundsViewInfo;
17struct FBounds4;
18
19#define SIMPLE_STREAMABLE_ASSET_MANAGER_ALLOW_DEBUG_POINTER !(UE_BUILD_SHIPPING)
20
21template<typename T, uint32 N>
23{
24public:
25 constexpr static uint32 MaxElements = N;
26 uint32 Reserve() { return ReservedIndex.fetch_add(1, std::memory_order_acq_rel); }
27
29 {
30 // can assert if Relased is equal ReservedIndex and lower than N
31 Storage[ItemReservedIndex] = MoveTemp(In);
32 }
33
35 {
36 uint32 Expected = ToRelease;
37 while (!ReleasedIndex.compare_exchange_weak(Expected, ToRelease + 1, std::memory_order_acq_rel))
38 {
39 Expected = ToRelease;
40 }
41 }
42
43 void WaitForWrites() const
44 {
45 while(ReleasedIndex.load(std::memory_order_acquire) < std::min(MaxElements, ReservedIndex.load(std::memory_order_acquire))){}
46 }
47
48 TArrayView<T> GetData() { return TArrayView<T>(Storage, ReleasedIndex.load()); };
49
50private:
51 std::atomic_uint32_t ReservedIndex = 0;
52 std::atomic_uint32_t ReleasedIndex = 0;
53 T Storage[MaxElements]{};
54};
55
56template<typename T>
58{
59public:
61
62 void Push(T&& In)
63 {
64 while (true)
65 {
66 FStorageShard* Storage = Shard.load(std::memory_order_acquire);
67 if (Storage)
68 {
69 const uint32 StorageIndex = Storage->Reserve();
70 if (StorageIndex < FStorageShard::MaxElements)
71 {
72 Storage->Store(MoveTemp(In), StorageIndex);
73 Storage->Release(StorageIndex);
74 return;
75 }
76 }
77 uint32 Expected = 0;
78 if (StorageAllocatorGuard.compare_exchange_strong(Expected, 1, std::memory_order_acq_rel))
79 {
81 if (Shard.compare_exchange_strong(Storage, NewStorage, std::memory_order_acq_rel))
82 {
83 if (Storage)
84 {
85 LockedStorage.Add(Storage);
86 }
87 }
88 else
89 {
90 delete NewStorage;
91 }
92 StorageAllocatorGuard.store(0, std::memory_order_release);
93 }
94 }
95 }
97 {
99 uint32 Expected = 0;
100 while (!StorageAllocatorGuard.compare_exchange_strong(Expected, 1, std::memory_order_acq_rel)){ Expected = 0; }
101 Shards = MoveTemp(LockedStorage);
102 FStorageShard* GrabbedStorage = Shard.exchange(nullptr);
103 StorageAllocatorGuard.store(0, std::memory_order_release);
104 if (GrabbedStorage)
105 {
106 GrabbedStorage->WaitForWrites();
108 }
109
110 return Shards;
111 }
112
121private:
122
123 std::atomic_uint32_t StorageAllocatorGuard = 0;
124 std::atomic<FStorageShard*> Shard = nullptr;
125 TArray<FStorageShard*> LockedStorage;
126};
127
129{
130public:
132 {
134 : CriticalSection(InCriticalSection)
135 , bShouldLock(bInShouldLock)
136 {
137 if (bShouldLock)
138 {
139 CriticalSection->Lock();
140 }
141 }
143 {
144 if (bShouldLock)
145 {
146 CriticalSection->Unlock();
147 }
148 }
149 private:
150 FCriticalSection* CriticalSection = nullptr;
151 bool bShouldLock = false;
152 };
153
155 {
157
158#if SIMPLE_STREAMABLE_ASSET_MANAGER_ALLOW_DEBUG_POINTER
159 union
160 {
163 };
164#endif
165
166 FUnregister() = default;
167 FUnregister(const FUnregister&) = default;
171
172 template<typename TObject>
179 };
180
209
251
252 struct FRegister : public FUpdate
253 {
255
256 FRegister() = default;
257 FRegister(const FRegister&) = default;
258 FRegister& operator=(const FRegister&) = default;
259 FRegister(FRegister&&) = default;
261
262 template<typename TObject, typename TPrimitive>
263 FRegister(const TObject* InObject, const TPrimitive* InPrimitive);
264 };
265
272
274 {
277#if SIMPLE_STREAMABLE_ASSET_MANAGER_ALLOW_DEBUG_POINTER
279#endif
280 friend bool operator==(const FAssetRecord& A, const FAssetRecord& B) { return A.AssetRegistrationIndex == B.AssetRegistrationIndex; }
281 };
282
284 {
287#if SIMPLE_STREAMABLE_ASSET_MANAGER_ALLOW_DEBUG_POINTER
289#endif
290 friend bool operator==(const FRemovedAssetRecord& A, const FRemovedAssetRecord& B) { return A.SimpleStreamableAssetManagerIndex == B.SimpleStreamableAssetManagerIndex; }
291 };
292
297private:
298 template <typename T>
299 struct TSimpleSparseArray
300 {
301 int32 Add(T&& InElement)
302 {
303 if (UsedElementsCount == FreeElementIndexHint)
304 {
305 UsedElements.Add(false, GSimpleStreamableAssetManagerSparseArrayGrowSize);
306 Elements.AddDefaulted(GSimpleStreamableAssetManagerSparseArrayGrowSize);
307 }
308 const int32 Index = UsedElements.FindAndSetFirstZeroBit(FreeElementIndexHint);
310 FreeElementIndexHint = Index + 1;
311 ++UsedElementsCount;
312 Elements[Index] = MoveTemp(InElement);
313 return Index;
314 }
315
316 void Reset(int32 Index)
317 {
318 if (UsedElements.Num() > Index && UsedElements[Index])
319 {
320 UsedElements[Index] = false;
321 FreeElementIndexHint = FMath::Min(FreeElementIndexHint, Index);
322 Elements[Index] = T{};
323 --UsedElementsCount;
324 }
325 }
326
327 void Empty()
328 {
329 FreeElementIndexHint = 0;
330 UsedElementsCount = 0;
331 UsedElements.Empty();
332 Elements.Empty();
333 }
334
335 int32 Num() const { return UsedElementsCount; }
336
337 SIZE_T GetAllocatedSize(void) const
338 {
339 return sizeof(TSimpleSparseArray)
340 + UsedElements.GetAllocatedSize()
341 + Elements.GetAllocatedSize();
342 }
343
344 TConstArrayView<T> GetSparseView() const
345 {
346 const int32 Max = UsedElements.FindLast(true);
347 return TConstArrayView<T>{ Elements.GetData(), Max + 1};
348 }
349 private:
350 int32 FreeElementIndexHint = 0;
351 int32 UsedElementsCount = 0;
352 TBitArray<> UsedElements;
353 TArray<T> Elements;
354 };
355
356 static FAutoConsoleVariableRef CVarUseSimpleStreamableAssetManager;
357 ENGINE_API static int32 GUseSimpleStreamableAssetManager;
358
359 static FAutoConsoleVariableRef CVarUseSimpleStreamableAssetManagerSparseArrayGrowSize;
360 ENGINE_API static int32 GSimpleStreamableAssetManagerSparseArrayGrowSize;
361
362 static FAutoConsoleVariableRef CVarUseSimpleStreamableAssetManagerEnsureAssetUniqueOnRegistration;
363 ENGINE_API static int32 GSimpleStreamableAssetManagerEnsureAssetUniqueOnRegistration;
364
365 static FAutoConsoleVariableRef CVarSimpleStreamableAssetManagerConsiderVisibility;
366 ENGINE_API static int32 GSimpleStreamableAssetManagerConsiderVisibility;
367
368 static FSimpleStreamableAssetManager* Instance;
369 FCriticalSection CriticalSection;
370
373 TLocklessGrowingStorage<FUnregister> UnregisterRecords;
375 TLocklessGrowingStorage<FUpdateLastRenderTime> UpdateLastRenderTimeRecords;
376
377 // ** Variables to manage Object registration ** //
378 int32 RegisteredObjectCount = 0;
379 int32 MaxObjects = 0;
380
381 int32 FreeObjectIndexHint = 0;
382 TBitArray<> ObjectUsedIndices;
383 TArray<TArray<FAssetRecord>> ObjectRegistrationIndexToAssetProperty;
384 TArray<FBounds4> ObjectBounds4;
385
386 void RegisterRecord(FRegister& Record);
387 void UpdateRecord(FUpdate& Record);
388 void UpdateRecord(FUpdateLastRenderTime& Record);
389 void UnregisterRecord(FUnregister& Record);
390
391 // ** Variables to manage Bounds registration ** //
392 void SetBounds(int32 BoundsIndex, const FBoxSphereBounds& Bounds, uint32 PackedRelativeBox, float StreamingScaleFactor, float LastRenderTime, const FVector4& RangeOrigin, float MinDistanceSq, float MinRangeSq, float MaxRangeSq);
393 FBoxSphereBounds GetBounds(int32 BoundsIndex) const;
394
395 // ** Variables to manage Assets registration ** //
396 int32 FreeAssetIndexHint = 0;
397 int32 UsedAssetIndices = 0;
398 TBitArray<> AssetUsedIndices;
399 TArray<TSimpleSparseArray<FAssetBoundElement>> AssetIndexToBounds4Index;
400 void AddRenderAssetElements(const TArrayView<FStreamingRenderAssetPrimitiveInfo>& RenderAssetInstanceInfos, int32 ObjectRegistrationIndex, bool bForceMipStreaming);
401 void RemoveRenderAssetElements(int32 ObjectRegistrationIndex);
402
403 // Used to update last render time
404 void TrySetLastRenderTime(int32 BoundsIndex, float LastRenderTime);
405
406 // ** Background task data** //
407 TArray<FBoundsViewInfo> BoundsViewInfos;
408
409 void GetRenderAssetScreenSize_Impl(
411 const int32 InAssetIndex,
412 float& MaxSize,
413 float& MaxSize_VisibleOnly,
415 const float MaxAssetSize,
416 const int32 MaxAllowedMip,
417 const TCHAR* LogPrefix) const;
418
419 void UpdateBoundSizes_Impl(
420 const TArray<FStreamingViewInfo>& ViewInfos,
421 const TArray<FStreamingViewInfoExtra, TInlineAllocator<4>>& ViewInfoExtras,
422 float LastUpdateTime,
423 const FRenderAssetStreamingSettings& Settings);
424
425 static void GetDistanceAndRange(
426 const FUpdate& Record,
427 float& MinDistanceSq, float& MinRangeSq, float& MaxRangeSq);
428
429 void UpdateTask_Async();
430
431 void GetAssetReferenceBounds_Impl(const UStreamableRenderAsset* Asset, TArray<FBox>& AssetBoxes) const;
432 uint32 GetAllocatedSize_Impl() const;
433public:
434 static FCriticalSection* GetCriticalSection() { return Instance ? &Instance->CriticalSection : nullptr; }
435
436 ENGINE_API static void Register(FRegister&& Record);
437 ENGINE_API static void Unregister(FUnregister&& Record);
438 ENGINE_API static void Update(FUpdate&& Record);
439 ENGINE_API static void Update(FUpdateLastRenderTime&& Record);
440
441 static bool IsEnabled() { return GUseSimpleStreamableAssetManager != 0; }
442 static bool ShouldConsiderVisibility() { return GSimpleStreamableAssetManagerConsiderVisibility != 0; }
443 static void Init();
444 static void Shutdown();
445 static void Process();
446
448
449 static uint32 GetAllocatedSize();
450
451 static void UpdateBoundSizes(
452 const TArray<FStreamingViewInfo>& ViewInfos,
453 const TArray<FStreamingViewInfoExtra, TInlineAllocator<4>>& ViewInfoExtras,
454 float LastUpdateTime,
455 const FRenderAssetStreamingSettings& Settings);
456
457 static void GetRenderAssetScreenSize(
459 const int32 InAssetIndex,
460 float& MaxSize,
461 float& MaxSize_VisibleOnly,
463 const float MaxAssetSize,
464 const int32 MaxAllowedMip,
465 const TCHAR* LogPrefix);
466
468
469 template<typename TObject>
470 static float GetStreamingScaleFactor(const TObject* Object, const FMatrix& LocalToWorld);
471};
472
473template<typename TObject>
475{
476 return Object->CanApplyStreamableRenderAssetScaleFactor() ? LocalToWorld.GetMaximumAxisScale() : 1.f;
477}
478
479template<typename TObject, typename TPrimitive>
481 : FUpdate(
482 InObject,
483 InObject->SimpleStreamableAssetManagerIndex,
484 InPrimitive->Bounds,
485 FSimpleStreamableAssetManager::GetStreamingScaleFactor(InObject, InPrimitive->GetRenderMatrix()),
486 InObject->GetMinDrawDistance(),
487 InObject->GetMaxDrawDistance(),
488 InObject->GetPrimitiveSceneInfo()->LastRenderTime,
489 InObject->IsForceMipStreaming())
490{
491 if (InObject->IsSupportingStreamableRenderAssetsGathering())
492 {
493 InObject->GetStreamableRenderAssetInfo(InPrimitive->Bounds, Assets);
494 }
495 else if (const IPrimitiveComponent* Interface = InPrimitive->GetPrimitiveComponentInterface())
496 {
497 Interface->GetStreamableRenderAssetInfo(Assets);
498 }
499 else
500 {
501 // Primitive has to support at least one of the two ways of providing assets
502 checkNoEntry();
503 }
504}
505
506inline int32 GetTypeHash(const FSimpleStreamableAssetManager::FAssetRecord& Object) { return Object.AssetRegistrationIndex; }
#define check(expr)
Definition AssertionMacros.h:314
#define checkNoEntry()
Definition AssertionMacros.h:316
@ INDEX_NONE
Definition CoreMiscDefines.h:150
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::UPTRINT UPTRINT
An unsigned integer the same size as a pointer.
Definition Platform.h:1146
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
@ Num
Definition MetalRHIPrivate.h:234
int32 GetTypeHash(const FSimpleStreamableAssetManager::FAssetRecord &Object)
Definition SimpleStreamableAssetManager.h:506
#define SIMPLE_STREAMABLE_ASSET_MANAGER_ALLOW_DEBUG_POINTER
Definition SimpleStreamableAssetManager.h:19
EStreamableRenderAssetType
Definition StreamableRenderAsset.h:26
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
if(Failed) console_printf("Failed.\n")
UEBinkAudioDecodeInterface * Interface
Definition binka_ue_decode_test.cpp:24
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition IConsoleManager.h:1580
Definition PrimitiveSceneProxy.h:296
Definition SimpleStreamableAssetManager.h:129
static void GetAssetReferenceBounds(const UStreamableRenderAsset *Asset, TArray< FBox > &AssetBoxes)
Definition SimpleStreamableAssetManager.cpp:115
static void Shutdown()
Definition SimpleStreamableAssetManager.cpp:70
static uint32 GetAllocatedSize()
Definition SimpleStreamableAssetManager.cpp:103
static void GetRenderAssetScreenSize(EStreamableRenderAssetType AssetType, const int32 InAssetIndex, float &MaxSize, float &MaxSize_VisibleOnly, int32 &MaxNumForcedLODs, const float MaxAssetSize, const int32 MaxAllowedMip, const TCHAR *LogPrefix)
Definition SimpleStreamableAssetManager.cpp:131
static void UnregisterAsset(UStreamableRenderAsset *InAsset)
Definition SimpleStreamableAssetManager.cpp:86
static float GetStreamingScaleFactor(const TObject *Object, const FMatrix &LocalToWorld)
Definition SimpleStreamableAssetManager.h:474
static void UpdateBoundSizes(const TArray< FStreamingViewInfo > &ViewInfos, const TArray< FStreamingViewInfoExtra, TInlineAllocator< 4 > > &ViewInfoExtras, float LastUpdateTime, const FRenderAssetStreamingSettings &Settings)
Definition SimpleStreamableAssetManager.cpp:121
static FCriticalSection * GetCriticalSection()
Definition SimpleStreamableAssetManager.h:434
static void Init()
Definition SimpleStreamableAssetManager.cpp:64
static bool ShouldConsiderVisibility()
Definition SimpleStreamableAssetManager.h:442
static void Process()
Definition SimpleStreamableAssetManager.cpp:76
static bool IsEnabled()
Definition SimpleStreamableAssetManager.h:441
static ENGINE_API void Unregister(FUnregister &&Record)
Definition SimpleStreamableAssetManager.cpp:162
Definition ComponentInterfaces.h:59
Definition ArrayView.h:139
Definition Array.h:670
Definition SimpleStreamableAssetManager.h:58
TArray< FStorageShard * > ExtractShards()
Definition SimpleStreamableAssetManager.h:96
~TLocklessGrowingStorage()
Definition SimpleStreamableAssetManager.h:113
TLocklessStaticStorage< T, 512 > FStorageShard
Definition SimpleStreamableAssetManager.h:60
void Push(T &&In)
Definition SimpleStreamableAssetManager.h:62
Definition SharedPointer.h:692
Definition ContainerAllocationPolicies.h:894
Definition StreamableRenderAsset.h:37
SIZE_T GetAllocatedSize(const T &Value)
Definition ManagedArray.h:93
U16 Index
Definition radfft.cpp:71
Definition TextureInstanceView.h:24
Definition TextureInstanceView.h:79
Definition TextureStreamingHelpers.h:72
Definition SimpleStreamableAssetManager.h:267
float TexelFactor
Definition SimpleStreamableAssetManager.h:269
int32 ObjectRegistrationIndex
Definition SimpleStreamableAssetManager.h:268
uint32 bForceLOD
Definition SimpleStreamableAssetManager.h:270
Definition SimpleStreamableAssetManager.h:274
const UStreamableRenderAsset * StreamableRenderAsset_ForDebug
Definition SimpleStreamableAssetManager.h:278
int32 AssetElementIndex
Definition SimpleStreamableAssetManager.h:276
int32 AssetRegistrationIndex
Definition SimpleStreamableAssetManager.h:275
friend bool operator==(const FAssetRecord &A, const FAssetRecord &B)
Definition SimpleStreamableAssetManager.h:280
Definition SimpleStreamableAssetManager.h:294
int32 BoundsIndex
Definition SimpleStreamableAssetManager.h:295
Definition SimpleStreamableAssetManager.h:253
FRegister & operator=(const FRegister &)=default
TArray< FStreamingRenderAssetPrimitiveInfo > Assets
Definition SimpleStreamableAssetManager.h:254
FRegister & operator=(FRegister &&)=default
FRegister(const FRegister &)=default
Definition SimpleStreamableAssetManager.h:284
const UStreamableRenderAsset * StreamableRenderAsset_ForDebug
Definition SimpleStreamableAssetManager.h:288
TSharedPtr< int32, ESPMode::ThreadSafe > SimpleStreamableAssetManagerIndex
Definition SimpleStreamableAssetManager.h:285
int32 AssetElementIndex
Definition SimpleStreamableAssetManager.h:286
friend bool operator==(const FRemovedAssetRecord &A, const FRemovedAssetRecord &B)
Definition SimpleStreamableAssetManager.h:290
Definition SimpleStreamableAssetManager.h:132
FScopedLock(FCriticalSection *InCriticalSection, bool bInShouldLock)
Definition SimpleStreamableAssetManager.h:133
~FScopedLock()
Definition SimpleStreamableAssetManager.h:142
Definition SimpleStreamableAssetManager.h:155
TSharedPtr< int32, ESPMode::ThreadSafe > ObjectRegistrationIndex
Definition SimpleStreamableAssetManager.h:156
FUnregister & operator=(const FUnregister &)=default
FUnregister(const TObject *Object)
Definition SimpleStreamableAssetManager.h:173
FUnregister & operator=(FUnregister &&)=default
const FPrimitiveSceneProxy * SceneProxy_ForDebug
Definition SimpleStreamableAssetManager.h:162
FUnregister(const FUnregister &)=default
UPTRINT ObjectKey
Definition SimpleStreamableAssetManager.h:161
Definition SimpleStreamableAssetManager.h:182
UPTRINT ObjectKey
Definition SimpleStreamableAssetManager.h:187
FUpdateLastRenderTime(const void *InObject, const TSharedPtr< int32, ESPMode::ThreadSafe > &InObjectRegistrationIndex, const float InLastRenderedTime)
Definition SimpleStreamableAssetManager.h:198
const FPrimitiveSceneProxy * SceneProxy_ForDebug
Definition SimpleStreamableAssetManager.h:188
FUpdateLastRenderTime(FUpdateLastRenderTime &&)=default
TSharedPtr< int32, ESPMode::ThreadSafe > ObjectRegistrationIndex
Definition SimpleStreamableAssetManager.h:183
FUpdateLastRenderTime & operator=(FUpdateLastRenderTime &&)=default
FUpdateLastRenderTime(const FUpdateLastRenderTime &)=default
FUpdateLastRenderTime & operator=(const FUpdateLastRenderTime &)=default
float LastRenderedTime
Definition SimpleStreamableAssetManager.h:191
Definition SimpleStreamableAssetManager.h:211
UPTRINT ObjectKey
Definition SimpleStreamableAssetManager.h:217
TSharedPtr< int32, ESPMode::ThreadSafe > ObjectRegistrationIndex
Definition SimpleStreamableAssetManager.h:212
float MaxDistance
Definition SimpleStreamableAssetManager.h:223
FUpdate(const void *InObject, const TSharedPtr< int32, ESPMode::ThreadSafe > &InObjectRegistrationIndex, const FBoxSphereBounds &InBounds, float InStreamingScaleFactor, const float InMinDistance, const float InMaxDistance, const float InLastRenderedTime, bool InForceMipStreaming)
Definition SimpleStreamableAssetManager.h:233
FUpdate & operator=(FUpdate &&)=default
float LastRenderedTime
Definition SimpleStreamableAssetManager.h:224
uint8 bForceMipStreaming
Definition SimpleStreamableAssetManager.h:225
FBoxSphereBounds ObjectBounds
Definition SimpleStreamableAssetManager.h:213
const FPrimitiveSceneProxy * SceneProxy_ForDebug
Definition SimpleStreamableAssetManager.h:218
float StreamingScaleFactor
Definition SimpleStreamableAssetManager.h:221
float MinDistance
Definition SimpleStreamableAssetManager.h:222
FUpdate(const FUpdate &)=default
FUpdate & operator=(const FUpdate &)=default
Definition TextureStreamingTypes.h:37
Definition TextureInstanceView.h:92
Definition ContentStreaming.h:75
Definition SimpleStreamableAssetManager.h:23
uint32 Reserve()
Definition SimpleStreamableAssetManager.h:26
void Release(uint32 ToRelease)
Definition SimpleStreamableAssetManager.h:34
TArrayView< T > GetData()
Definition SimpleStreamableAssetManager.h:48
void WaitForWrites() const
Definition SimpleStreamableAssetManager.h:43
static constexpr uint32 MaxElements
Definition SimpleStreamableAssetManager.h:25
void Store(T &&In, uint32 ItemReservedIndex)
Definition SimpleStreamableAssetManager.h:28
Definition BoxSphereBounds.h:25
T GetMaximumAxisScale() const
Definition Matrix.inl:618