UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
SparseVolumeTextureStreamingManager.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
8#include "IO/IoDispatcher.h"
11#include "RenderResource.h"
12#include "Containers/Map.h"
15#include "RenderGraphBuilder.h"
16#include "Misc/DateTime.h"
17
21
24
25namespace UE
26{
27 namespace DerivedData
28 {
29 class FRequestOwner; // Can't include DDC headers from here, so we have to forward declare
31 }
32}
33
34namespace UE
35{
36namespace SVT
37{
38
39struct FResources;
40struct FMipLevelStreamingInfo;
41class FTextureRenderResources;
42class FTileDataTexture;
43class FTileUploader;
44class FPageTableUpdater;
45struct FStreamingInstanceRequest;
46class FStreamingInstance;
47
48// Helper class for managing slots in the tile data texture (SVT streaming pool). It uses a priority queue to reuse older slots that haven't been referenced for some (render) frames.
50{
51public:
52 static constexpr uint32 PhysicalCoordMask = (1u << 24u) - 1u; // Lower 24 bits are used for storing XYZ in 8 bit each. Upper 8 bit can be used by the caller.
53
54 // Describes a slot in the tile data texture and the current tile that is mapped to it.
56 {
57 uint32 TileIndexInFrame; // Index of the tile in the array of tiles of the SVT frame.
58 uint16 FrameIndex; // Index of the SVT frame this tile belongs to.
59 uint16 bIsLocked : 1; // Locked tiles are not in the priority queue and will never be streamed out/replaced unless manually freed.
60 uint16 bIsAllocated : 1; // Whether this slot is currently occupied by a tile.
61
65 };
66
68
69 // Allocate a tile. Returns a packed 8|8|8 coordinate into the tile data texture or INDEX_NONE if there is no more space.
70 // UpdateIndex is the index of the current tick/update.
71 // FreeThreshold is an additional buffer to how many updates must have passed until a tile may be reused.
72 // FrameIndex is the index of the SVT frame and TileIndexInFrame is the index of the tile for which we try to allocate a slot.
73 // TilePriority is used to sort tiles in the priority queue. Higher values make the tile stream out after other tiles with lower values.
74 // If bLocked is true, then the tile will never be automatically streamed out.
75 // OutPreviousAllocation is a description of the old tile that occupied the newly allocated slot.
76 uint32 Allocate(uint32 UpdateIndex, uint32 FreeThreshold, uint16 FrameIndex, uint32 TileIndexInFrame, uint32 TilePriority, bool bLocked, FAllocation& OutPreviousAllocation);
77
78 // Marks a tile as still in use. See Allocate() for a description of the parameters.
80
81 // Frees a given tile. Expects the output of Allocate(), i.e. a packed 8|8|8 coordinate. Freed tiles are placed at the front of the priority queue for tile reuse.
82 void Free(uint32 TileCoord);
83
84 // Returns the size of the memory allocated for bookkeeping.
86
87private:
89 TArray<FAllocation> Allocations; // One entry for every slot in the tile data texture. Maps to the current SVT frame occupying that tile
90 FIntVector3 ResolutionInTiles = FIntVector3::ZeroValue;
91 uint32 TileCapacity = 0;
92 uint32 NumAllocated = 0;
93};
94
96{
97public:
100
101 //~ Begin FRenderResource Interface.
102 virtual void InitRHI(FRHICommandListBase& RHICmdList) override;
103 virtual void ReleaseRHI() override;
104 //~ End FRenderResource Interface.
105
106 //~ Begin IStreamingManager Interface.
110 virtual void Update_GameThread() override;
111
112 virtual void Request(UStreamableSparseVolumeTexture* SparseVolumeTexture, uint32 StreamingInstanceKey, float FrameRate, float FrameIndex, float MipLevel, EStreamingRequestFlags Flags) override;
113 virtual void BeginAsyncUpdate(FRDGBuilder& GraphBuilder, bool bUseAsyncThread) override;
114 virtual void EndAsyncUpdate(FRDGBuilder& GraphBuilder) override;
115 virtual const FStreamingDebugInfo* GetStreamingDebugInfo(FRDGBuilder& GraphBuilder) const override;
116 //~ End IStreamingManager Interface.
117
118private:
120
121 // One per frame of each SVT
122 struct FFrameInfo
123 {
124 const FResources* Resources; // Initialized on the game thread
125 FTextureRenderResources* TextureRenderResources; // Initialized on the game thread
126
127 int32 NumMipLevels = 0; // Number of actual mip levels of this frame. Depending on virtual volume extents, frames can have different numbers of levels.
128 TArray<uint32> TileAllocations; // TileAllocations[PhysicalTileIndex]
129 TBitArray<> ResidentPages; // One bit for every (non-zero) page (in the sparse page octree) for all mip levels, starting at the highest mip
130 TBitArray<> InvalidatedPages; // Temporarly needed when patching the page table. Marks all pages that require an update
131 TBitArray<> ResidentTiles; // Tiles that are actually resident in GPU memory
132 TBitArray<> StreamingTiles; // Tiles that have logically been streamed in but may not actually be resident in GPU memory yet because the IO request hasn't finished
133 TMap<uint32, uint32> TileIndexToPendingRequestIndex;
134 TRefCountPtr<IPooledRenderTarget> PageTableTexture;
135
136 SIZE_T GetAllocatedSize() const;
137 };
138
139 // Streaming manager internal data for each SVT
140 struct FStreamingInfo
141 {
142 uint16 SVTHandle = INDEX_NONE;
143 FName SVTName = FName();
144 EPixelFormat FormatA = PF_Unknown;
145 EPixelFormat FormatB = PF_Unknown;
146 FVector4f FallbackValueA = FVector4f();
147 FVector4f FallbackValueB = FVector4f();
148 int32 NumPrefetchFrames = 0;
149 float PrefetchPercentageStepSize = 0.0f;
150 float PrefetchPercentageBias = 0.0f;
151 TArray<FFrameInfo> PerFrameInfo;
152 TArray<TUniquePtr<FStreamingInstance>> StreamingInstances;
153 TArray<uint32, TInlineAllocator<16>> MipLevelStreamingSize; // MipLevelStreamingSize[MipLevel] * FrameRate is the required IO bandwidth in bytes/s to stream a given MipLevel.
154
155 FTileAllocator TileAllocator;
156 TUniquePtr<FTileDataTexture> TileDataTexture;
157
158 // Tries to look up an existing FStreamingInstance, creates a new one if it can't find one and finally updates it with the new request.
160
161 SIZE_T GetAllocatedSize() const;
162 };
163
164 // Represents an IO request for tile(s)
165 struct FPendingRequest
166 {
167 uint16 SVTHandle = INDEX_NONE;
168 uint16 FrameIndex = INDEX_NONE;
169 uint32 TileOffset = INDEX_NONE;
170 uint32 TileCount = 0;
171#if WITH_EDITORONLY_DATA
172 // When in editor, DDC requests finish on another thread, so we need to guard against race conditions.
174 FSharedBuffer SharedBuffer;
175 enum class EState
176 {
177 None,
179 DDC_Ready,
181 Memory,
182 Disk,
183 } State = EState::None;
184 uint32 RetryCount = 0;
186#endif
187 FIoBuffer RequestBuffer;
188 FBulkDataBatchRequest Request;
189 uint32 IssuedInFrame = 0;
190 bool bBlocking = false;
191
192 bool IsValid() const { return SVTHandle != uint16(INDEX_NONE); }
193
195 {
196 SVTHandle = InSVTHandle;
197 FrameIndex = InFrameIndex;
198 TileOffset = InTileOffset;
199 TileCount = InTileCount;
200 IssuedInFrame = InIssuedInFrame;
201 bBlocking = bInBlocking;
202 }
203
204 void Reset()
205 {
206 SVTHandle = INDEX_NONE;
207 FrameIndex = INDEX_NONE;
208 TileOffset = INDEX_NONE;
209 TileCount = INDEX_NONE;
210#if WITH_EDITORONLY_DATA
211 SharedBuffer.Reset();
212 State = EState::None;
213 RetryCount = 0;
215#endif
216 if (Request.IsPending())
217 {
218 Request.Cancel();
219 Request.Wait(); // Even after calling Cancel(), we still need to Wait() before we can touch the RequestBuffer.
220 }
221 Request.Reset();
222 RequestBuffer = {};
223 IssuedInFrame = 0;
224 bBlocking = false;
225 }
226 };
227
228 // Encapsulates all the src/dst pointers for memcpy-ing the streamed data into GPU memory.
229 // See the comment on FMipLevelStreamingInfo for details about these pointers.
230 struct FTileDataTask
231 {
232 TStaticArray<uint8*, 2> DstOccupancyBitsPtrs;
233 TStaticArray<uint8*, 2> DstTileDataOffsetsPtrs;
234 TStaticArray<uint8*, 2> DstTileDataPtrs;
235 uint8* DstPhysicalTileCoordsPtr;
236 TStaticArray<const uint8*, 2> SrcOccupancyBitsPtrs;
237 TStaticArray<const uint8*, 2> SrcVoxelDataPtrs;
238 TStaticArray<uint32, 2> VoxelDataSizes;
239 TStaticArray<uint32, 2> VoxelDataBaseOffsets;
240 uint32 PhysicalTileCoord;
241 };
242
243 struct FAsyncState
244 {
245 int32 NumReadyRequests = 0;
246 bool bUpdateActive = false;
247 bool bUpdateIsAsync = false;
248 };
249
250 // Stores info extracted from the UStreamableSparseVolumeTexture and its USparseVolumeTextureFrames so that we don't need to access these uobjects on the rendering thread
251 struct FNewSparseVolumeTextureInfo
252 {
253 UStreamableSparseVolumeTexture* SVT = nullptr; // Do not dereference!
254 FName SVTName = FName();
255 EPixelFormat FormatA = PF_Unknown;
256 EPixelFormat FormatB = PF_Unknown;
257 FVector4f FallbackValueA = FVector4f(0.0f, 0.0f, 0.0f, 0.0f);
258 FVector4f FallbackValueB = FVector4f(0.0f, 0.0f, 0.0f, 0.0f);
259 int32 NumMipLevelsGlobal = 0;
260 float StreamingPoolSizeFactor = 0.0f;
261 int32 NumPrefetchFrames = 0;
262 float PrefetchPercentageStepSize = 0.0f;
263 float PrefetchPercentageBias = 0.0f;
264 TArray<FFrameInfo> FrameInfo; // Only Resources and TextureRenderResources are initialized
265 };
266
267 // Uniquely identifies the mip level of a frame in a static or animated SparseVolumeTexture
268 struct FFrameKey
269 {
270 uint16 SVTHandle = INDEX_NONE;
271 uint16 FrameIndex = INDEX_NONE;
272
273 friend FORCEINLINE uint32 GetTypeHash(const FFrameKey& Key) { return HashCombine(GetTypeHash(Key.SVTHandle), GetTypeHash(Key.FrameIndex)); }
274 FORCEINLINE bool operator==(const FFrameKey& Other) const { return (SVTHandle == Other.SVTHandle) && (FrameIndex == Other.FrameIndex); }
275 FORCEINLINE bool operator!=(const FFrameKey& Other) const { return !(*this == Other); }
276 FORCEINLINE bool operator<(const FFrameKey& Other) const { return SVTHandle != Other.SVTHandle ? SVTHandle < Other.SVTHandle : FrameIndex < Other.FrameIndex; }
277 };
278
279 // The payload associated with a request for a given frame of a SVT
280 struct FRequestPayload
281 {
282 FStreamingInstance* StreamingInstance = nullptr;
283 uint16 MipLevelMask = 0; // Bitmask of requested mip levels
284 float LowestMipFraction = 0.0f; // Setting this to a value between 0 and less than 1 signifies that only a certain percentage of pages in this mip level should be streamed
285 TStaticArray<uint8, 16> Priorities = TStaticArray<uint8, 16>(InPlace, 0); // Priority for each mip level with a set bit in MipLevelMask
286 };
287
288 struct FStreamingRequest
289 {
290 FFrameKey Key;
291 FRequestPayload Payload;
292 };
293
294 // Represents a contiguous range of tiles in a given frame of a SVT. This is the output of filtering FStreamingRequest and is used to generate FPendingRequests.
295 struct FTileRange
296 {
297 uint16 SVTHandle = INDEX_NONE;
298 uint16 FrameIndex = INDEX_NONE;
299 uint32 TileOffset = INDEX_NONE;
300 uint32 TileCount = 0;
301 uint8 Priority = 0; // Higher value means higher priority
302 };
303
304 TMap<UStreamableSparseVolumeTexture*, uint16> SparseVolumeTextureToHandle; // Do not dereference the key! We just read the pointer itself.
306 TMap<FFrameKey, FRequestPayload> RequestsHashTable;
307 TArray<FPendingRequest> PendingRequests; // Do not access any members of an element before first calling LOCK_PENDING_REQUEST() on the element!
308#if WITH_EDITORONLY_DATA
311#endif
312
314 FGraphEventArray AsyncTaskEvents;
315 FAsyncState AsyncState;
316 int32 MaxPendingRequests = 0;
317 int32 NumPendingRequests = 0;
318 int32 NextPendingRequestIndex = 0;
319 uint32 UpdateIndex = 1;
320 FDateTime InitTime = FDateTime::Now(); // The precise time doesn't matter, we only use it as a basis to compute time as a double.
321 int64 TotalRequestedBandwidth = 0;
322
323 // Transient lifetime
324 TSet<FStreamingInstance*> ActiveStreamingInstances; // Instances that have had a request in them since the last update
325 TSet<FTileDataTexture*> TileDataTexturesToUpdate;
326 TSet<FFrameInfo*> InvalidatedSVTFrames; // Set of SVT frames where tiles have been streamed in or out. Used in PatchPageTable().
327 TArray<FTileRange> TileRangesToStream; // Output of FilterRequests(), consumed in IssueRequests().
328 TArray<FTileDataTask> UploadTasks; // Accessed on the async thread
329 TBitArray<> ResidentPagesNew; // Used as temporary memory in PatchPageTable()
330 TBitArray<> ResidentPagesDiff; // Used as temporary memory in PatchPageTable()
331
332 void AddInternal(FRDGBuilder& GraphBuilder, FNewSparseVolumeTextureInfo&& NewSVTInfo);
334 void AddRequest(const FStreamingRequest& Request);
335 void AsyncUpdate();
336 void ComputeBandwidthLimit();
337 void FilterRequests();
338 void IssueRequests();
339 int32 DetermineReadyRequests();
340 void InstallReadyRequests();
341 void PatchPageTable(FRDGBuilder& GraphBuilder); // Patches the page table to reflect streamed in/out pages and to ensure non-resident mip levels fall back to coarser mip level tile data
342 FStreamingInfo* FindStreamingInfo(uint16 SparseVolumeTextureHandle); // Returns nullptr if the key can't be found
343 FStreamingInfo* FindStreamingInfo(UStreamableSparseVolumeTexture* SparseVolumeTexture); // Returns nullptr if the key can't be found
344 int32 AllocatePendingRequestIndex(); // Allocates a request in the PendingRequests array. Returns INDEX_NONE when out of slots.
345
346#if WITH_EDITORONLY_DATA
347 UE::DerivedData::FCacheGetChunkRequest BuildDDCRequest(const FResources& Resources, uint32 FirstTileIndex, uint32 NumTiles, uint32 PendingRequestIndex, int32 ChunkIndex);
349#endif
350
351 SIZE_T GetAllocatedSize() const;
352};
353
354}
355}
#define FORCEINLINE
Definition AndroidPlatform.h:140
@ INDEX_NONE
Definition CoreMiscDefines.h:150
@ InPlace
Definition CoreMiscDefines.h:162
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
#define DECLARE_MEMORY_STAT_POOL_EXTERN(CounterName, StatId, GroupId, Pool, API)
Definition Stats.h:688
#define DECLARE_STATS_GROUP(GroupDesc, GroupId, GroupCat)
Definition Stats.h:689
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
bool operator<(const FTextFormatString &LHS, const FTextFormatString &RHS)
Definition ITextFormatArgumentModifier.h:147
void Init()
Definition LockFreeList.h:4
#define DECLARE_LOG_CATEGORY_EXTERN(CategoryName, DefaultVerbosity, CompileTimeVerbosity)
Definition LogMacros.h:361
UE::Math::TVector4< float > FVector4f
Definition MathFwd.h:75
UE_FORCEINLINE_HINT bool IsValid(const UObject *Test)
Definition Object.h:1875
EPixelFormat
Definition PixelFormat.h:16
@ PF_Unknown
Definition PixelFormat.h:17
constexpr uint32 HashCombine(uint32 A, uint32 C)
Definition TypeHash.h:36
uint8_t uint8
Definition binka_ue_file_header.h:8
uint16_t uint16
Definition binka_ue_file_header.h:7
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition BinaryHeap.h:20
Definition BulkData.h:1295
Definition IoBuffer.h:15
Definition NameTypes.h:617
Definition RenderGraphBuilder.h:49
Definition RHICommandList.h:455
Definition RenderResource.h:37
Definition HttpRequestPayload.h:17
Definition SharedBuffer.h:341
CORE_API void Reset()
Definition SharedBuffer.cpp:242
Definition Array.h:670
Definition UnrealString.h.inl:34
Definition RefCounting.h:454
Definition SparseArray.h:524
Definition StaticArray.h:26
Definition UniquePtr.h:107
Definition SparseVolumeTextureStreamingInstance.h:34
Definition SparseVolumeTextureStreamingManager.h:96
virtual void InitRHI(FRHICommandListBase &RHICmdList) override
Definition SparseVolumeTextureStreamingManager.cpp:160
virtual void ReleaseRHI() override
Definition SparseVolumeTextureStreamingManager.cpp:179
virtual const FStreamingDebugInfo * GetStreamingDebugInfo(FRDGBuilder &GraphBuilder) const override
Definition SparseVolumeTextureStreamingManager.cpp:553
virtual void BeginAsyncUpdate(FRDGBuilder &GraphBuilder, bool bUseAsyncThread) override
Definition SparseVolumeTextureStreamingManager.cpp:340
virtual void Remove_GameThread(UStreamableSparseVolumeTexture *SparseVolumeTexture) override
Definition SparseVolumeTextureStreamingManager.cpp:230
virtual void Update_GameThread() override
Definition SparseVolumeTextureStreamingManager.cpp:256
virtual void EndAsyncUpdate(FRDGBuilder &GraphBuilder) override
Definition SparseVolumeTextureStreamingManager.cpp:513
virtual void Request(UStreamableSparseVolumeTexture *SparseVolumeTexture, uint32 StreamingInstanceKey, float FrameRate, float FrameIndex, float MipLevel, EStreamingRequestFlags Flags) override
Definition SparseVolumeTextureStreamingManager.cpp:273
virtual void Add_GameThread(UStreamableSparseVolumeTexture *SparseVolumeTexture) override
Definition SparseVolumeTextureStreamingManager.cpp:187
virtual void Request_GameThread(UStreamableSparseVolumeTexture *SparseVolumeTexture, uint32 StreamingInstanceKey, float FrameRate, float FrameIndex, float MipLevel, EStreamingRequestFlags Flags) override
Definition SparseVolumeTextureStreamingManager.cpp:243
Definition SparseVolumeTextureStreamingManager.cpp:139
Definition SparseVolumeTexture.h:261
Definition SparseVolumeTextureStreamingManager.h:50
SIZE_T GetAllocatedSize() const
Definition SparseVolumeTextureStreamingManager.cpp:2119
void UpdateUsage(uint32 UpdateIndex, uint32 TileCoord, uint32 TilePriority)
Definition SparseVolumeTextureStreamingManager.cpp:2081
uint32 Allocate(uint32 UpdateIndex, uint32 FreeThreshold, uint16 FrameIndex, uint32 TileIndexInFrame, uint32 TilePriority, bool bLocked, FAllocation &OutPreviousAllocation)
Definition SparseVolumeTextureStreamingManager.cpp:2023
static constexpr uint32 PhysicalCoordMask
Definition SparseVolumeTextureStreamingManager.h:52
Definition ISparseVolumeTextureStreamingManager.h:56
Definition SparseVolumeTexture.h:366
Definition SparseVolumeTexture.h:452
uint32 GetTypeHash(const FKey &Key)
Definition BlackboardKey.h:35
bool operator!=(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:506
bool operator==(const FCachedAssetKey &A, const FCachedAssetKey &B)
Definition AssetDataMap.h:501
State
Definition PacketHandler.h:88
EStreamingRequestFlags
Definition ISparseVolumeTextureStreamingManager.h:47
Definition AdvancedWidgetsModule.cpp:13
Definition DateTime.h:76
static CORE_API FDateTime Now()
Definition DateTime.cpp:377
@ MCR_GPU
Definition GenericPlatformMemory.h:252
static const TIntVector3 ZeroValue
Definition IntVector.h:45
Definition SparseVolumeTexture.h:194
Definition ISparseVolumeTextureStreamingManager.h:17
Definition SparseVolumeTextureStreamingInstance.h:15
Definition SparseVolumeTextureStreamingManager.h:56
FAllocation()
Definition SparseVolumeTextureStreamingManager.h:62
uint16 bIsLocked
Definition SparseVolumeTextureStreamingManager.h:59
uint16 FrameIndex
Definition SparseVolumeTextureStreamingManager.h:58
FAllocation(uint16 InFrameIndex, uint32 InTileIndex, bool bInIsLocked, bool bInIsAllocated)
Definition SparseVolumeTextureStreamingManager.h:63
uint16 bIsAllocated
Definition SparseVolumeTextureStreamingManager.h:60
uint32 TileIndexInFrame
Definition SparseVolumeTextureStreamingManager.h:57