RenderBatchData.h
Source/MassBattle/Public/Fragments/RenderBatchData.h
概述 Overview
渲染批次的宿主侧数据缓冲集合。三类结构:Agent 批次 FAgentRenderBatchData(每槽位实例身份、变换、LOD、样式、动画轨道、插值输入、文本数据)、FX 批次 FFxRenderBatchData(附加 FX 的槽位数据,含 Niagara 唯一身份与父级真值插值输入)与文本数据 FTextRenderData(带自旋锁的弹字缓冲)。批次的每个数据数组由对应 bUse*Array 标志门控,在批次创建时按 Niagara 系统是否暴露匹配的 User.* 变量置位——向后兼容机制。批次数据既不是 fragment 也不是快照实体,是处理器与 Niagara NS 之间的并行写入缓冲。
Host-side data buffers for render batches. Three kinds: agent batch FAgentRenderBatchData (per-slot instance identity, transforms, LOD, style, anim tracks, interp inputs, text data), FX batch FFxRenderBatchData (attached-FX slot data including Niagara identity and parent ground-truth interp inputs), and text data FTextRenderData (spin-locked popup-text buffers). Each data array is gated by a matching bUse*Array flag set at batch creation when the Niagara system exposes the corresponding User.* variable — a backward-compatibility mechanism. These are not fragments or snapshot entities; they are parallel-write buffers between processors and the Niagara NS.
FTextRenderData USTRUCT
文本(弹字)渲染缓冲:位置数组 + 值/样式/缩放/偏移打包数组。带可重入自旋锁(std::atomic<bool> 互斥),支持多线程并行写入。拷贝构造 / 赋值只复制两个数组(不复制锁)。两个数组均带 TInlineAllocator<32>,小批量写入无堆分配。
Text (popup) render buffer: a location array plus a packed value/style/scale/offset array. Carries a re-entrant spin lock (std::atomic<bool> mutex) for parallel multi-thread writes. Copy constructor / assignment copy only the two arrays (not the lock). Both arrays use TInlineAllocator<32> so small batches allocate nothing on the heap.
成员变量 Members
| 名称 Name | 类型 Type | 默认值 | 说明 Description |
|---|---|---|---|
LockFlag | std::atomic<bool> (private) | false | 私有自旋锁标志。Private spin-lock flag. |
Text_Location_Array | TArray<FVector, TInlineAllocator<32>> | 空 | 文本世界位置数组。Text world-location array. |
Text_Value_Style_Scale_Offset_Array | TArray<FVector4f, TInlineAllocator<32>> | 空 | 文本打包数组(值、样式、缩放、偏移)。Packed text array (value, style, scale, offset). |
方法 Methods
自旋获取锁:对 LockFlag 做 acquire 语义的 exchange,占用中则忙等。
Spins to acquire the lock: exchange on LockFlag with acquire semantics, busy-waiting while held.
Input
无参数。
No parameters.
Output
无返回值。副作用:锁被当前线程占用。
No return value. Side effect: the lock is held by the calling thread.
释放锁:以 release 语义把 LockFlag 存回 false。
Releases the lock: stores false into LockFlag with release semantics.
Input
无参数。
No parameters.
Output
无返回值。副作用:锁释放,其它线程可获取。
No return value. Side effect: the lock is released for other threads.
为两个数组预分配容量,避免写入期堆分配。
Pre-allocates capacity for both arrays to avoid heap allocation during writes.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
NumToReserve | int32 | 预分配的元素数。Number of elements to reserve. |
Output
无返回值。副作用:两个数组的容量增长。
No return value. Side effect: both arrays' capacity grows.
FAgentRenderBatchData USTRUCT
Agent 渲染批次数据:一批 Niagara 实例(默认容量 4096)的全部槽位状态。按槽位并行的数组集合(槽位复用冷却、隐藏标记、变换、LOD、样式、健康条、动画轨道、插值输入、身份令牌、相对变换)。Phase C 起支持 GPU 侧插值:NS 暴露 User.* 变量时,处理器把原始目标值(速度 / 角速度 / 插值参数 / 相对变换 / 动画轨道)推给 GPU 插值,并由 UniqueIDArray 身份令牌取代旧的 WasHidden 边沿检测;配套两处复用跳变修复——修复 B(复用首个引擎帧推送 token ^ TokenFlipBit,GPU 必然观测到令牌变化)与修复 A(冷却语义改为引擎帧墙钟时间)。批量写入前调用 Reserve 预分配。
Agent render batch data: all slot state for one Niagara instance batch (default capacity 4096). A set of slot-parallel arrays (slot-reuse cooldowns, hidden flags, transforms, LOD, style, health bar, anim tracks, interp inputs, identity tokens, relative transforms). Since Phase C the NS can interpolate on the GPU: when it exposes User.* variables, the processor pushes raw targets (velocity / angular velocity / interp params / relative transform / anim tracks) for GPU interpolation, and the UniqueIDArray identity token replaces the old unreliable WasHidden edge detection; two reuse-snap fixes accompany it — fix B (the first engine frame of a reuse pushes token ^ TokenFlipBit, so the GPU always observes a token change) and fix A (cooldown semantics become engine-frame wall time). Call Reserve before bulk writes.
成员变量 Members
| 名称 Name | 类型 Type | 默认值 | 说明 Description |
|---|---|---|---|
SpawnedNiagaraSystem | TObjectPtr<UNiagaraComponent> | nullptr | 已生成的 Niagara 系统组件。Spawned Niagara system component. |
BatchSize | int32 | 4096 | 批次容量(Reserve 时更新)。Batch size (updated by Reserve). |
IdleRemoveCountdown | float | -1.0f | 空闲移除倒计时(负值 = 不自动移除)。Idle remove countdown (negative = no auto removal). |
FreeSlotArray | TArray<bool> | 空 | 槽位空闲标记。Per-slot free flag. |
IsHiddenArray | TArray<bool> | 空 | 槽位隐藏标记。Per-slot hidden flag. |
CoolDowns | TArray<float> | 空 | 槽位复用冷却——防止同帧回收(对应 FFxRenderBatchData::CoolDowns_Attached)。冷却语义 = 引擎帧墙钟时间(它保障的是「GPU 观测到 hidden/-1 间隔」,而 GPU 活在引擎帧边界):每引擎帧按 RenderDeltaTime 递减一次,绝不每模拟 tick 按 SimDeltaTime 递减——一个引擎帧内 30 个 tick 的追帧 drain 曾把整段冷却无形蒸发(复用跳变修复 A,见 LastCooldownDecrementFrame)。Slot-reuse cooldown preventing same-tick recycling (mirrors FFxRenderBatchData::CoolDowns_Attached). Cooldown semantics are ENGINE-FRAME wall time (the guarantee it enforces is "the GPU observes the hidden/-1 gap", and the GPU lives at engine-frame boundaries): decremented once per engine frame by RenderDeltaTime, never once per sim tick by SimDeltaTime — a catch-up drain of 30 sim ticks in one engine frame used to evaporate the whole cooldown invisibly (reuse-snap fix A, see LastCooldownDecrementFrame). |
LocationArray | TArray<FVector> | 空 | 槽位世界位置。Per-slot world locations. |
OrientationArray | TArray<FQuat4f> | 空 | 槽位朝向。Per-slot orientations. |
ScaleArray | TArray<FVector3f> | 空 | 槽位缩放。Per-slot scales. |
DynamicParams0_Array | TArray<FVector4f> | 空 | 通用动态参数(bit-cast 打包)。Generic dynamic params (bit-cast packed). |
HealthBar_Opacity_CurrentRatio_TargetRatio_Array | TArray<FVector3f> | 空 | 血条打包数据(不透明度、当前比例、目标比例)。Packed health-bar data (opacity, current ratio, target ratio). |
CurrentLODArray | TArray<int32> | 空 | 槽位当前 LOD。以 MeshIndex_Array 推送——LOD 透传。Per-slot current LOD. Pushed as MeshIndex_Array — LOD passthrough. |
StyleArray | TArray<int32> | 空 | 槽位样式索引。Per-slot style index. |
bUseMeshIndexArray | bool | false | 是否使用网格索引数组(遗留标志)。Whether a mesh-index array is in use (legacy flag). |
VelocityArray | TArray<FVector3f> | 空 | 原始 CachedVelocity,用于变换预测插值(Phase C)。Raw CachedVelocity, for predictive transform interpolation (Phase C). |
AngVelArray | TArray<FVector3f> | 空 | 原始 CachedAngularVelocity(弧度/秒轴角向量),供 GPU 旋转预测。Raw CachedAngularVelocity (rad/s axis·angle vec), for GPU rotational prediction. |
InterpParamsArray | TArray<FVector4f> | 空 | 插值参数 (InterpSpeed, PredictTime, SnapDist, bEnabled?1:0)。Interp params (InterpSpeed, PredictTime, SnapDist, bEnabled?1:0). |
AnimTracksA | TArray<FVector4f> | 空 | 压缩动画轨道 A:X=StartFrame0(u16)|EndFrame0(u16) Y=StartFrame1|EndFrame1 Z=StartFrame2|EndFrame2 W=FPS0×16(u16)|FPS1×16(u16)。Compressed anim tracks A: X=StartFrame0(u16)|EndFrame0(u16) Y=StartFrame1|EndFrame1 Z=StartFrame2|EndFrame2 W=FPS0×16(u16)|FPS1×16(u16). |
AnimTracksB | TArray<FVector4f> | 空 | 压缩动画轨道 B:X=FPS2×16(u16)|Loop0(b16)|Loop1(b17)|Loop2(b18)|pad。Compressed anim tracks B: X=FPS2×16(u16)|Loop0(b16)|Loop1(b17)|Loop2(b18)|pad. |
UniqueIDArray | TArray<int32> | 空 | 每槽位身份令牌:占用 Agent 的 UniqueID(0 = 空/隐藏)。GPU 与粒子上次身份比较检测池复用并跳变——取代不可靠的 WasHidden 边沿检测(同帧回收、上传延迟、休眠帧)。Identity token per slot: the occupying agent's UniqueID (0 = empty/hidden). The GPU compares this against the particle's last-known identity to detect pool reuse and snap — replaces the unreliable WasHidden edge detection (same-tick reuse, upload latency, dormant frames). |
TokenFlipUntilFrameArray | TArray<uint32> | 空 | 复用跳变修复 B:槽位复用的首个引擎帧推送 token ^ TokenFlipBit(符号位,在 UID/Gen 令牌空间之外)而非真实令牌——GPU 在任何复用时都必然观测到跨引擎帧边界的令牌变化,跳变必然触发;即使 min-free 分配器把死亡占用者的 UID 回收给了新 spawn(令牌相同)、且 -1 哨兵帧被多逻辑 tick 追帧 drain 吞掉(GPU 每引擎帧只看最后一次推送)。元素值 = 推送翻转令牌截止的引擎帧号(GFrameNumber)。Reuse-snap fix B: on slot REUSE the first engine frame pushes token ^ TokenFlipBit (the sign bit, outside the UID/Gen token space) instead of the real token — the GPU therefore always observes a token CHANGE across an engine-frame boundary on reuse, so the snap fires even when the min-free UID allocator recycled the dead occupant's UID into the new spawn (identical token) and even when the cooldown/-1 sentinel frames were swallowed by a multi-tick catch-up drain (the GPU only sees the last push per engine frame). Each element is the engine frame number (GFrameNumber) until which this slot pushes the flipped token. |
LastCooldownDecrementFrame | uint64 | 0 | 复用跳变修复 A 的配套标记:上次递减冷却的引擎帧号——保证 CoolDowns 每引擎帧至多按 RenderDeltaTime 递减一次,而非每模拟 tick 按 SimDeltaTime 递减。Companion marker for reuse-snap fix A: the engine frame of the last cooldown decrement — ensuring CoolDowns decrements at most once per engine frame by RenderDeltaTime, not once per sim tick by SimDeltaTime. |
RelLocArray | TArray<FVector3f> | 空 | parent+relative 模型(新 NS):父级(agent)到 mesh 渲染变换的相对偏移。parent+relative model (new NS): relative offset from the parent (agent) to the mesh render transform. |
RelRotArray | TArray<FQuat4f> | 空 | 相对旋转。Relative rotation. |
RelScaleArray | TArray<FVector3f> | 空 | 相对缩放。Relative scale. |
TextData | FTextRenderData | — | 文本渲染数据(弹字)。Text render data (popups). |
bUsePositionArray | bool | false | 是否使用位置数组(遗留标志)。Whether the position array is in use (legacy flag). |
bUseStyleArray | bool | false | 是否推送样式数组。Whether the style array is pushed. |
bNewPredictionModel | bool | false | 为真当且仅当 NS 暴露任一 Rel* 数组 → 父级真值模型;否则旧自身世界模型。True iff the NS exposes any Rel* array → parent-GT model; else the old own-world model. |
bUseVelocityArray | bool | false | Phase C 逐数组向后兼容标志:NS 暴露 User.VelocityArray 时置位。Phase C per-array backward-compat flag: set when the NS exposes User.VelocityArray. |
bUseAngVelArray | bool | false | NS 暴露角速度数组时置位。Set when the NS exposes the angular velocity array. |
bUseInterpParamsArray | bool | false | NS 暴露插值参数数组时置位。Set when the NS exposes the interp params array. |
bUseParentScaleArray | bool | false | NS 暴露父级缩放数组时置位。Set when the NS exposes the parent scale array. |
bUseAnimTracksA / bUseAnimTracksB | bool ×2 | false | NS 暴露动画轨道数组 A/B 时置位。Set when the NS exposes anim track arrays A/B. |
bUseRelLocArray | bool | false | NS 暴露 User.RelLocArray → 新 parent+relative 模型。NS exposes User.RelLocArray → new parent+relative model. |
bUseRelRotArray / bUseRelScaleArray | bool ×2 | false | NS 暴露相对旋转 / 缩放数组时置位。Set when the NS exposes the relative rotation / scale arrays. |
bUseUniqueIDArray | bool | false | NS 暴露 User.UniqueIDArray 时置位。Set when the NS exposes User.UniqueIDArray. |
方法 Methods
批量写入前的预分配:更新 BatchSize 并为全部按槽位数组预留容量(含 TextData)。
Pre-allocation before bulk writes: updates BatchSize and reserves capacity on every per-slot array (including TextData).
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
NumToReserve | int32 | 批次容量。Batch capacity. |
Output
无返回值。副作用:BatchSize 更新,全部数组容量增长。
No return value. Side effects: BatchSize updated, all array capacities grow.
FFxRenderBatchData USTRUCT
FX 渲染批次数据:一批附加 FX 的 Niagara 实例(默认容量 2048)的槽位状态。旧 NS 模型推 FX 自身世界变换(LocationArray_Attached 等);新 NS 模型推父级真值 + 相对变换(ParentLocArray_Attached 等),由 GPU 用 User.ElapsedSinceLogicTick 插值。每个发送由其 bUse*Array 标志门控,仅在 NS 暴露匹配 User.* 变量时置位。另有 burst 小数组(TInlineAllocator<32>)供一次性批量(如生成瞬间)使用。
FX render batch data: slot state for a batch of attached-FX Niagara instances (default capacity 2048). The old-NS model pushes the FX's own world transform (LocationArray_Attached etc.); the new-NS model pushes parent ground truth + relative transform (ParentLocArray_Attached etc.), interpolated on the GPU via User.ElapsedSinceLogicTick. Each send is gated by its bUse*Array flag, set only when the NS exposes the matching User.* variable. Small burst arrays (TInlineAllocator<32>) serve one-shot bulk writes (e.g. spawn moments).
成员变量 Members
| 名称 Name | 类型 Type | 默认值 | 说明 Description |
|---|---|---|---|
SpawnedNiagaraSystem | TObjectPtr<UNiagaraComponent> | nullptr | 已生成的 Niagara 系统组件。Spawned Niagara system component. |
BatchSize | int32 | 2048 | 批次容量(Reserve 时更新)。Batch size (updated by Reserve). |
CoolDown | float | 3.f | 槽位冷却时长。Slot cooldown duration. |
IdleRemoveCountdown | float | -1.0f | 空闲移除倒计时(负值 = 不自动移除)。Idle remove countdown (negative = no auto removal). |
FreeSlotArray_Attached | TArray<bool> | 空 | 槽位空闲标记。比 bitarray 慢但利于多线程性能(可无锁写)。Per-slot free flag. Slower than a bitarray but good for multithreading performance (lock-free writes). |
NextFreeSlot_Attached | int32 | 0 | O(1) 槽位分配游标(FxRenderProcessor Stage 3 用)。每个模拟 tick 重置为 0(Stage 1 重置路径),使注册循环向前走而非 O(N) Find 扫描。Cursor for O(1) slot allocation (FxRenderProcessor Stage 3). Reset to 0 each sim tick (Stage 1 reset path) so the registration loop walks forward instead of O(N) Find scans. |
IsHiddenArray_Attached | TArray<bool> | 空 | 槽位隐藏标记。Per-slot hidden flag. |
CoolDowns_Attached | TArray<float> | 空 | 槽位复用冷却——防止同帧回收。Slot-reuse cooldown preventing same-tick recycling. |
NiagaraIDIndex_Attached | TArray<int32> | 空 | 每槽位 Niagara 身份索引(Epoch)。Per-slot Niagara identity index (Epoch). |
NiagaraIDAcquireTag_Attached | TArray<int32> | 空 | 每槽位 Niagara 身份计数(Counter)。Per-slot Niagara identity counter. |
StyleArray_Attached | TArray<int32> | 空 | 槽位样式索引。Per-slot style index. |
LocationArray_Attached | TArray<FVector> | 空 | FX 自身世界位置(旧 NS 模型)。FX own-world location (old-NS model). |
OrientationArray_Attached | TArray<FQuat4f> | 空 | FX 自身世界旋转(旧 NS 模型)。FX own-world rotation (old-NS model). |
ScaleArray_Attached | TArray<FVector3f> | 空 | FX 自身世界缩放(旧 NS 模型)。FX own-world scale (old-NS model). |
ParentLocArray_Attached | TArray<FVector> | 空 | 父级真值位置(新 NS 模型,GPU 插值输入)。Parent ground-truth location (new-NS model, GPU interp input). |
ParentVelArray_Attached | TArray<FVector3f> | 空 | 父级真值速度(外推用)。Parent ground-truth velocity (for extrapolation). |
ParentAngularVelocityArray_Attached | TArray<FVector3f> | 空 | 父级角速度(弧度/秒,旋转外推用)。Parent angular velocity (rad/s, for rotational extrapolation). |
InterpParamsArray_Attached | TArray<FVector4f> | 空 | 父级插值参数 (InterpSpeed, PredictTime, SnapDist, bEnabled?1:0),供 GPU 平滑。Parent interp params (InterpSpeed, PredictTime, SnapDist, bEnabled?1:0) for GPU smoothing. |
ParentScaleArray_Attached | TArray<FVector3f> | 空 | 父级缩放(来自 FScaling),用于偏移+缩放组合。Parent scale (from FScaling) for offset+scale composition. |
ParentRotArray_Attached | TArray<FQuat4f> | 空 | 父级真值旋转(四元数)。Parent ground-truth rotation (quat). |
RelLocArray_Attached | TArray<FVector3f> | 空 | FFxVisualizing.RelativeTransform 位置。FFxVisualizing.RelativeTransform location. |
RelRotArray_Attached | TArray<FQuat4f> | 空 | RelativeTransform 旋转。RelativeTransform rotation. |
RelScaleArray_Attached | TArray<FVector3f> | 空 | RelativeTransform 缩放。RelativeTransform scale. |
LocationArray_Burst | TArray<FVector, TInlineAllocator<32>> | 空 | burst 位置数组(一次性批量)。Burst location array (one-shot bulk). |
OrientationArray_Burst / ScaleArray_Burst / StyleArray_Burst | TArray<…, TInlineAllocator<32>> | 空 | burst 朝向 / 缩放 / 样式数组。Burst orientation / scale / style arrays. |
bUseStyleArray | bool | false | 是否推送样式数组。Whether the style array is pushed. |
bUseParentLocArray | bool | false | NS 暴露 User.ParentLocArray_Attached 时置位。Set when the NS exposes User.ParentLocArray_Attached. |
bUseParentPositionArray | bool | false | 门控 — 仅在 NS 暴露 User.PositionArray_Attached (LWC Position 变量) 时推送。Gated — pushed only when the NS exposes User.PositionArray_Attached (LWC Position variable). |
bUseParentVelArray | bool | false | NS 暴露父级速度数组时置位。Set when the NS exposes the parent velocity array. |
bUseParentAngularVelocityArray | bool | false | NS 暴露父级角速度数组时置位。Set when the NS exposes the parent angular velocity array. |
bUseInterpParamsArray | bool | false | NS 暴露插值参数数组时置位。Set when the NS exposes the interp params array. |
bUseParentScaleArray | bool | false | NS 暴露父级缩放数组时置位。Set when the NS exposes the parent scale array. |
bUseParentRotArray | bool | false | NS 暴露父级旋转数组时置位。Set when the NS exposes the parent rotation array. |
bUseRelLocArray / bUseRelRotArray / bUseRelScaleArray | bool ×3 | false | NS 暴露相对变换数组时置位。Set when the NS exposes the relative transform arrays. |
bUseNiagaraIDIndexArray | bool | false | NS 暴露 User.NiagaraIDIndex_Attached (Int32 数组) 时置位。Set when the NS exposes User.NiagaraIDIndex_Attached (Int32 array). |
bUseNiagaraIDAcquireTagArray | bool | false | NS 暴露 User.NiagaraIDAcquireTag_Attached (Int32 数组) 时置位。Set when the NS exposes User.NiagaraIDAcquireTag_Attached (Int32 array). |
bNewPredictionModel | bool | false | 新模型当且仅当 NS 暴露任一相对变换数组。New model iff the NS exposes any relative-transform array. |
bCpuInterpMode | bool | false | 批次有 ≥1 个 CPU 插值槽位 → 无论是否有 Rel 数组都推送旧模型(FX 世界变换写入 LocationArray)。Batch has ≥1 CPU-interp slot → push the old model (FX world-space on LocationArray) regardless of Rel arrays. |
bCpuInterpDirty | bool | false | 每帧:本帧有 CPU 插值槽位更新 → 串行推送(良性并行写)。Per-frame: a CPU-interp slot was updated this frame → push serially (benign parallel write). |
方法 Methods
批量写入前的预分配:更新 BatchSize 并为全部按槽位数组预留容量。
Pre-allocation before bulk writes: updates BatchSize and reserves capacity on every per-slot array.
Input
| 参数 Param | 类型 Type | 说明 Description |
|---|---|---|
NumToReserve | int32 | 批次容量。Batch capacity. |
Output
无返回值。副作用:BatchSize 更新,全部数组容量增长。
No return value. Side effects: BatchSize updated, all array capacities grow.
清空四个 burst 数组(位置 / 朝向 / 缩放 / 样式),用于每次 burst 使用后复位。
Clears the four burst arrays (location / orientation / scale / style), used to reset after each burst use.
Input
无参数。
No parameters.
Output
无返回值。副作用:四个 burst 数组清空(容量保留)。
No return value. Side effect: the four burst arrays are emptied (capacity kept).
管线角色 Pipeline Role
在 MassBattle 管线中的位置:批次数据由 MassBattleAgentRenderProcessor / MassBattleFxRenderProcessor 填充并推送给 Niagara(SpawnedNiagaraSystem 的 User.* 数据通道),MassBattleHostMonoProcessor 参与批次的创建与维护。批次不是锁步实体——不参与快照 / hash,但槽位身份令牌(UniqueIDArray / NiagaraIDIndex_Attached 对)保证池复用后渲染身份可检测。
Position in the MassBattle pipeline: batch data is filled and pushed to Niagara (the User.* data channel of SpawnedNiagaraSystem) by MassBattleAgentRenderProcessor / MassBattleFxRenderProcessor, with MassBattleHostMonoProcessor participating in batch creation and upkeep. Batches are not lockstep entities — they do not enter snapshot/hash — but the slot identity tokens (UniqueIDArray / the NiagaraIDIndex_Attached pair) make render identity detectable after pool reuse.