fix(render): retain surfaceless particle metadata

Preserve a successfully decoded GfxObj ParticleGfxInfo when SurfaceId is zero and condition only texture acquisition. Missing/no-Gfx descriptors retain Default behavior; material, additive, routing, and untextured drawing remain unchanged.

Add a production-path GfxObj-backed synthetic no-surface pin with distinct authored/AABB centers, non-unit size, nonidentity orientation, object/particle merge order, visual center, and unassigned texture-slot assertions. Correct the synthetic-DAT evidence wording and advance only the S4-c3a ledger row.

Final F2 source audit found no defect: preparation holds reconstruction inputs only; Append reserves once; false and exception roll back the exact tail once; first-use rejection remains registered; accepted tokens stay stable; independent 3000-entry caps preserve row-2 immediate duplicates; flush/end/abort/next-preparation cleanup converges; retained capacity/bytes remain bounded; warmed production paths remain 0 B.

Gates: no-surface target 1/1; unchanged section 19 baseline 95/95; AP boundary/count 1/1; real allocations 2/2 at 0 B; shader/manifest 32/32; Release solution 0 warnings/0 errors; diff-check pass. No graphical client.

Mutation: restoring eea5793d2's SurfaceId-zero-to-Default ternary first failed CellTurn_GfxObjBillboardWithoutSurfaceRetainsAuthoredSortCenterAndUntexturedFallback at the authored-distance assertion, expected 40 actual 100.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-04 14:09:50 +02:00
parent 8bd75ba312
commit b6b0156045
4 changed files with 202 additions and 8 deletions

View file

@ -1114,14 +1114,16 @@ public sealed unsafe partial class ParticleRenderer : IDisposable
_particleGfxInfoByGfxObj[gfxObjId] = info;
}
resolved = info.SurfaceId == 0
? ParticleGfxInfo.Default
: info with
resolved = info;
if (info.SurfaceId != 0)
{
resolved = info with
{
TextureSlot = _textures.AcquireParticleTexture(
emitter.Handle,
info.SurfaceId),
};
}
_particleGfxInfoByEmitter.Add(emitter.Handle, resolved);
return resolved;
}