UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
LandscapeGrassMapsBuilder.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "CoreMinimal.h"
5#include "Async/AsyncWork.h"
11
13struct FScopedSlowTask;
14
15namespace UE::Landscape
16{
17 enum class EBuildFlags : uint8;
18} // namespace UE::Landscape
19
39
44{
45public:
48
49#if WITH_EDITOR
51 UE_DEPRECATED(5.6, "Use the function with the EBuildFlags param")
52 LANDSCAPE_API void Build();
54
57#endif // WITH_EDITOR
58
59 // count components that have valid data but whose generation hash does not match
61
62 // called when components are registered to the world
63 void RegisterComponent(ULandscapeComponent* Component);
64 // called when components are unregistered from the world.
65 void UnregisterComponent(const ULandscapeComponent* Component);
66
67 // get the number of grass maps that are still waiting to render, as of the last AmortizedUpdateGrassMaps()
68 int32 GetTotalGrassMapsWaitingToRender() const { return TotalComponentsWaitingCount; }
69
70 // Amortized Update of Grass Maps near the specified cameras.
71 // if Cameras is empty, it considers all distances to be zero for update purposes:
72 // - it won't evict anything for distance
73 // - it will not start tracking (building grass maps) for any components
75
76 // synchronous build of grassmaps for a specific set of components
77 // returns true if it successfully makes all LandscapeComponents have up to date Grass Maps.
79
80#if !UE_BUILD_SHIPPING
81 // Force stream textures and issue draw calls for the specified components -- mainly for capturing the rendering behavior and debugging issues
82 // (this will evict existing populated grass maps on those components)
84#endif // !UE_BUILD_SHIPPING
85
86private:
87
88 // false if this program instance will never be able to render grass
89 bool CanEverRender() const;
90
91 // false if the world can not currently render the grass (but this may change later, for example if preview modes are modified)
92 bool CanCurrentlyRender() const;
93
94 // Update all of the non-pending components. Returns true if any components changed states.
95 // If passed an empty Cameras array, distances are calculated as zero (i.e. it won't evict for distance)
96 // MaxExpensiveUpdateChecksToPerform controls how many expensive component updates are performed (pass ComponentStates.Num() to process all)
97 // bCancelAndEvictAllImmediately will move all tracked component states to the pending state and block until any in-flight processing is cancelled and cleaned up
98 // bEvictWhenBeyondEvictionRange will evict any populated components that are beyond the eviction range distance (used to reclaim memory when using runtime generation)
99 // DeltaTicks specifies how many ticks to advance the tick counter on each tracked component. In general 1 tick, though in some cases where we are iterating within a single frame, and don't need to trigger delayed-tick events (i.e. D3D11 readback), we can pass 0.
101
102 // Start the grass map generation process on pending components in priority order
103 // (based on distance from the given Camera set) -- Cameras must not be empty.
104 void StartPrioritizedGrassMapGeneration(const TArray<FVector>& Cameras, int32 MaxComponentsToStart, bool bOnlyWhenCloserThanEvictionRange);
105
106 enum class EComponentStage : uint8
107 {
108 Pending, // initial state; the component is waiting to start the generation process.
109 NotReady, // tried to start generation process, but either no grass types exist or the material is not ready. wait for that to change.
110 TextureStreaming, // texture streaming was requested. wait for the mips to be available
111 Rendering, // GPU render commands were sent -- waiting for async readback to complete
112 AsyncFetch, // Waiting for the async fetch task to complete
113 GrassMapsPopulated, // grass maps are built and are ready to create instances
114 };
115
116 struct FComponentState
117 {
118 public:
119 // this pointer is valid as long as the Component is registered
120 // (the FComponentState itself may continue to exist after unregistration, until all resources are cleaned up)
121 ULandscapeComponent* Component = nullptr;
122
123 EComponentStage Stage = EComponentStage::Pending;
124
125 bool bInPendingHeap = false;
126
127 // counts the number of ticks this component has remained in the current stage
128 int32 TickCount = 0;
129
130 #if WITH_EDITOR
131 // the hashes of dependencies when this component's grass map was built, for tracking automatic invalidation
134 #endif // WITH_EDITOR
135
136 // list of textures to stream prior to rendering this component (valid only in TextureSreaming and Rendering stages)
137 TArray<TWeakObjectPtr<UTexture>> TexturesToStream;
138
139 // the active render (valid only in Rendering stage)
141
142 // when in AsyncFetch stage, this is async task that we are waiting for
144
145 FComponentState(ULandscapeComponent* Component);
146
147 bool AreTexturesStreamedIn();
148 bool IsBeyondEvictionRange(const TArray<FVector>& Cameras) const;
149 };
150
151 // components in the Pending state are also tracked in a priority heap, using this structure
152 struct FPendingComponent
153 {
154 FPendingComponent(FComponentState* InComponentState)
156 {}
157
158 // comparison operator used for Heap functions -- smaller keys have priority over larger keys
159 bool operator<(const FPendingComponent& Other) const
160 {
161 return PriorityKey < Other.PriorityKey;
162 }
163
164 void UpdatePriorityDistance(const TArray<FVector>& Cameras, float MustHaveDistanceScale);
165
166 FComponentState* State = nullptr;
167 double PriorityKey = TNumericLimits<double>::Lowest();
168 };
169
170 // structure to do an amortized update of a set of update elements in a (conceptual) array
171 struct FAmortizedUpdate
172 {
173 // the first index to update this tick (inclusive)
174 int32 FirstIndex = 0;
175
176 // the last index to update this tick (exclusive)
177 int32 LastIndex = 0;
178
179 // Call at the beginning of the update tick to set up how many updates you want to run this tick
180 // UpdateElementCount is the total number of update elements (to wrap when we hit the end of the possibility space)
182 {
185 {
186 // if we are updating more than what we have, then just update everything
187 FirstIndex = 0;
188 LastIndex = UpdateElementCount;
189 }
190 else
191 {
192 FirstIndex = LastIndex;
193 if (FirstIndex >= UpdateElementCount)
194 {
195 FirstIndex = 0;
196 }
197 check(FirstIndex >= 0);
198 LastIndex = FirstIndex + MaxUpdatesThisFrame;
199 }
200 }
201
202 // return true if the given element should update
203 bool ShouldUpdate(int32 UpdateElementIndex)
204 {
205 if ((UpdateElementIndex >= FirstIndex) && (UpdateElementIndex < LastIndex))
206 {
207 return true;
208 }
209 return false;
210 }
211
212 // call if an update element is deleted from the array, to update the valid ranges
213 void HandleDeletion(int32 DeletedUpdateElementIndex)
214 {
215 if (DeletedUpdateElementIndex < FirstIndex)
216 {
217 FirstIndex--;
218 }
219 if (DeletedUpdateElementIndex < LastIndex)
220 {
221 LastIndex--;
222 }
223
224 }
225 };
226
227 UWorld* World = nullptr;
228
229 // counts of how many components are currently in each stage
230 int32 PendingCount = 0;
231 int32 NotReadyCount = 0;
232 int32 StreamingCount = 0;
233 int32 RenderingCount = 0;
234 int32 AsyncFetchCount = 0;
235 int32 PopulatedCount = 0;
236
237 // number of components that need to render but are waiting (as of the last call to StartTrackingComponents())
238 int32 TotalComponentsWaitingCount = 0;
239
240 // true if any render thread commands were queued by the last call to UpdateTrackedComponents()
241 bool bRenderCommandsQueuedByLastUpdate = false;
242
243 TAllocatorFixedSizeFreeList<sizeof(FComponentState), 32> StatePoolAllocator;
244
245 // store the grass map state of each registered (or recently unregistered) component
247
248 // Pending components, in a min heap by distance to streaming cameras
249 TArray<FPendingComponent> PendingComponentsHeap;
250 int32 FirstNewPendingComponent = TNumericLimits<int32>::Max();
251 int32 PendingUpdateAmortizationCounter = 0;
252 float LastMustHaveDistanceScale = 0.0f; // used to detect spawn distance scales changing
253
254 // state to amortize the update of components
255 FAmortizedUpdate AmortizedUpdate;
256
257 // system to manage texture streaming requests
258 FLandscapeTextureStreamingManager& TextureStreamingManager;
259
260 // hash grid storing previously used camera locations (to determine when cameras have jumped)
262
263 // tries to cancel any in flight operations and transition back to the Pending state
264 // returns true when the state has been successfully transitioned back to Pending
265 // if bCancelImmediately is true, it will ensure the component reaches Pending state before returning (possibly blocking on async or gpu tasks)
266 bool CancelAndEvict(FComponentState& State, bool bCancelImmediately);
267
268 // try to kick off the grass map generation pipeline -- returns true if it started the amortized update path, false otherwise.
269 bool StartGrassMapGeneration(FComponentState& State, bool bForceCompileShaders, bool bTryFastPaths = true);
270
271 // try to apply fast path transitions to a pending component -- returns true if a fastpath was taken, and the component is no longer pending.
272 bool TryFastpathsFromPending(FComponentState& State, bool bRecalculateHashes);
273
274 // once textures are streamed, this kicks off the grass data render, and async GPU readback
275 void KickOffRenderAndReadback(FComponentState& State);
276
277 // once the GPU readback is complete, this starts processing the data to generate a GrassData structure
278 void LaunchAsyncFetchTask(FComponentState& State);
279
280 void PopulateGrassDataFromAsyncFetchTask(FComponentState& State);
281
282 // once the GPU readback is complete, this populates the grass data on the component (and cancels texture stream requests)
283 void PopulateGrassDataFromReadback(FComponentState& State);
284 void RemoveTextureStreamingRequests(FComponentState& State);
285
286 // state transition helpers
287 void StreamingToNotReady(FComponentState& State);
288 void PendingToNotReady(FComponentState& State);
289 void PendingToPopulatedFastPathAlreadyHasData(FComponentState& State);
290 void PendingToPopulatedFastPathNoGrass(FComponentState& State);
291 void PendingToStreaming(FComponentState& State);
292
293 // pending component heap add/remove
294 void AddToPendingComponentHeap(FComponentState* State);
295 void RemoveFromPendingComponentHeap(FComponentState* State);
296
297 void CompleteAllAsyncTasksNow();
298
299#if WITH_EDITOR
300 // cached count of how many grass maps are outdated, and the last time we calculated that value
301 mutable int32 OutdatedGrassMapCount = 0;
302 mutable double GrassMapsLastCheckTime = 0.0;
303#endif // WITH_EDITOR
304};
305
306
#define FORCEINLINE
Definition AndroidPlatform.h:140
#define check(expr)
Definition AssertionMacros.h:314
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define RETURN_QUICK_DECLARE_CYCLE_STAT(StatId, GroupId)
Definition Stats.h:655
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
bool operator<(const FTextFormatString &LHS, const FTextFormatString &RHS)
Definition ITextFormatArgumentModifier.h:147
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition LandscapeGrassMapsBuilder.h:21
TNonNullPtr< FLandscapeGrassWeightExporter > ActiveRender
Definition LandscapeGrassMapsBuilder.h:24
TMap< ULandscapeComponent *, TUniquePtr< FLandscapeComponentGrassData >, TInlineSetAllocator< 1 > > Results
Definition LandscapeGrassMapsBuilder.h:25
FAsyncFetchTask(FLandscapeGrassWeightExporter *ActiveRender)
Definition LandscapeGrassMapsBuilder.h:27
FORCEINLINE TStatId GetStatId() const
Definition LandscapeGrassMapsBuilder.h:34
void DoWork()
Definition LandscapeGrassMapsBuilder.cpp:422
Definition LandscapeGrassMapsBuilder.h:44
~FLandscapeGrassMapsBuilder()
Definition LandscapeGrassMapsBuilder.cpp:324
int32 CountOutdatedGrassMaps(const TArray< TObjectPtr< ULandscapeComponent > > &LandscapeComponents) const
void RegisterComponent(ULandscapeComponent *Component)
Definition LandscapeGrassMapsBuilder.cpp:778
bool BuildGrassMapsNowForComponents(TArrayView< TObjectPtr< ULandscapeComponent > > LandscapeComponents, FScopedSlowTask *SlowTask, bool bMarkDirty)
Definition LandscapeGrassMapsBuilder.cpp:1093
void DebugRenderComponents(TArrayView< TObjectPtr< ULandscapeComponent > > LandscapeComponents)
Definition LandscapeGrassMapsBuilder.cpp:947
int32 GetTotalGrassMapsWaitingToRender() const
Definition LandscapeGrassMapsBuilder.h:68
void UnregisterComponent(const ULandscapeComponent *Component)
Definition LandscapeGrassMapsBuilder.cpp:806
void AmortizedUpdateGrassMaps(const TArray< FVector > &Cameras, bool bPrioritizeCreation, bool bAllowStartGrassMapGeneration)
Definition LandscapeGrassMapsBuilder.cpp:842
Definition LandscapeGrassWeightExporter.h:101
Definition LandscapeTextureStreamingManager.h:33
Definition AsyncWork.h:663
Definition AllocatorFixedSizeFreeList.h:30
Definition ArrayView.h:139
Definition Array.h:670
Definition ContainerAllocationPolicies.h:1664
Definition UnrealString.h.inl:34
Definition NonNullPointer.h:23
Definition UniquePtr.h:107
Definition PointHashGrid3.h:33
Definition World.h:918
State
Definition PacketHandler.h:88
Definition Landscape.h:55
EBuildFlags
Definition LandscapeEditTypes.h:70
Definition ScopedSlowTask.h:32
Definition NumericLimits.h:41
Definition ObjectPtr.h:488
Definition LightweightStats.h:416