FSceneCulling MarkCellBoundsDirty(CellIndex, bStaticChanged, bDynamicChanged) (Engine/Source/Runtime/Renderer/Private/SceneCulling/SceneCulling.cpp, ~line 1907) assigns DirtyCellBoundsMaskStatic / DirtyCellBoundsMaskDynamic instead of accumulating them. When a cell is marked twice in the same frame (static first, then dynamic-only), the static flag is overwritten with false and the static chunk explicit bounds are never rebuilt. The GPU then culls against stale chunk bounds.
If you have multiple runtime PCG volumes in your scene, which use the HLSL point processor and GPU static mesh spawners, when you walk around the map, the runtime cells get culled in and out, depending on the camera angle.
DirtyCellBoundsMaskStatic[CellIndex] = bStaticChanged; DirtyCellBoundsMaskDynamic[CellIndex] = bDynamicChanged;
Accumulate the flags (OR) in MarkCellBoundsDirty rather than assign. Both masks are reset every frame (Init(false) ~2401-2402 / Empty ~2580-2581), so nothing leaks across frames.
if (bStaticChanged) { DirtyCellBoundsMaskStatic[CellIndex] = true; }
if (bDynamicChanged) { DirtyCellBoundsMaskDynamic[CellIndex] = true; }
A call with both flags false on an unmarked cell adds the index to DirtyCellBoundsIndices without setting either mask, so a later real mark adds the index a second time (duplicate chunk entries; harmless, pre-existing).
In one frame, have a static instance update in a cell (e.g. an ISM/grass instance update) followed by a dynamic mark in the same cell (any dynamic primitive instance update retained in that cell, or a cell finalize with only dynamic changes). Static chunk explicit bounds for that cell remain stale.
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-403021 in the post.
| 0 |
| Component | UE - Rendering - Architecture |
|---|---|
| Affects Versions | 5.8 |
| Target Fix | 5.9 |
| Created | Oct 14, 2026 |
|---|---|
| Updated | Oct 19, 2026 |