docs(overhaul): bound S4 c3a retail fix round
This commit is contained in:
parent
a86ec73ece
commit
8e0c6fb145
1 changed files with 114 additions and 0 deletions
|
|
@ -1432,3 +1432,117 @@ before the return matrix):
|
|||
10. Allocate one object in the real cell-merge path:
|
||||
`ProductionCellObjectParticleMerge_WarmedPathAllocatesZeroBytes` first
|
||||
expected 0, actual 3,072 managed bytes.
|
||||
|
||||
## 19. S4-c3a fix round 1 — authored particle CYpt and bounded preparation (lead, 2026-09-04)
|
||||
|
||||
The first retail-faithfulness lens returned **FAIL** on candidate
|
||||
`44e2bc227ba74d10074cfe985eee094e10b7f438`. Ordinary object parts are
|
||||
correct, but the billboard/mode-2–5 particle path orders by its rendered quad
|
||||
center. That center is the vertex-AABB-derived `ParticleGfxInfo.CenterOffset`
|
||||
after viewer-facing adjustment, not the GfxObj's authored `sort_center`.
|
||||
Retail does not use the rendered center for CYpt:
|
||||
`CPhysicsPart::UpdateViewerDistance @ 0x0050E030` reads the current GfxObj's
|
||||
`sort_center` at offsets `+0x7C/+0x80/+0x84`, scales it, passes it with the
|
||||
part `Position` to `Position::get_offset`, computes the length, and writes
|
||||
CYpt. The paired bytes at `0x0050E036..0x0050E0AE` confirm that named-decomp
|
||||
sequence. The same lens also found the stale statement that static records
|
||||
are never re-sorted downstream.
|
||||
|
||||
The lead's pre-production audit found two coupled safety holes in the new
|
||||
prepared-particle seam. `_preparedCellAlphaScratch` is a new retained list but
|
||||
is absent from the alpha scratch accounting/retention bound. More importantly,
|
||||
`PrepareForCellAlpha` reserves `_deferredAlpha` payload tokens before the
|
||||
driver reaches the queue visibility edge. An exception from a later immediate
|
||||
duplicate can strand unregistered source payload; ordinary capacity rejection
|
||||
retains payload for entries that can never draw. These contradict §18.3's
|
||||
source-owned rollback requirement. They are included in this same bounded
|
||||
round rather than deferred to a predictable production-lens failure.
|
||||
|
||||
### 19.1 F1 — one authored particle sort point, separate from its draw center
|
||||
|
||||
Retain `GfxObj.SortCenter` explicitly in `ParticleGfxInfo`. Populate it
|
||||
directly in `AuthoredParticleGfxInfo`; synthetic texture-only/default
|
||||
billboards, which have no GfxObj, use zero. Do not derive it from vertex bounds
|
||||
and do not replace or alter the visual `CenterOffset`.
|
||||
|
||||
For every billboard/mode-2–5 particle, compute the CYpt point before any
|
||||
viewer-facing draw-frame adjustment:
|
||||
|
||||
`particle.Position + Transform(authoredSortCenter * particle.Size, ParticleOrientation)`.
|
||||
|
||||
Use the squared viewer distance from that point for `ParticleInstance` and
|
||||
`ParticleSubmission`. The rendered quad position/axes remain byte-for-byte
|
||||
the existing `CenterOffset`/facing result. The full-mesh path already applies
|
||||
the equivalent `ObjectRenderData.SortCenter` through its model; keep the two
|
||||
paths semantically identical and do not add a second sort.
|
||||
|
||||
Add a real GfxObj-backed billboard test whose authored SortCenter is distinct
|
||||
from both its particle origin and vertex AABB center, with non-unit size and a
|
||||
non-identity orientation. Drive the actual cell particle preparation and
|
||||
driver merge against ordinary object alpha. It must prove that the authored
|
||||
point determines the cross-source order while the captured billboard draw
|
||||
center remains the existing visual center. Required mutations: using rendered
|
||||
`pos`, using the AABB center, dropping size, or dropping orientation must each
|
||||
fail a named first assertion.
|
||||
|
||||
### 19.2 F2 — reserve only at the queue visibility edge and roll back rejection
|
||||
|
||||
A prepared particle record retains only the information needed to reconstruct
|
||||
its source payload when `Append` is called; preparation must not mutate
|
||||
`_deferredAlpha`. At `Append`, reserve one tail token, call
|
||||
`RetailAlphaQueue.TryAppend`, and roll back that exact tail token when the
|
||||
append returns false or throws. A rejected first-use source must remain
|
||||
registered by the queue and receive one flush/end/abort reset, but it owns no
|
||||
rejected payload and never prepares or draws it. Accepted token indices remain
|
||||
stable. An exception from a later row-5 or clip-immediate draw during
|
||||
preparation must leave the source payload count unchanged.
|
||||
|
||||
Bound `_preparedCellAlphaScratch` by the physical two-list limit: retain no
|
||||
more than the first 3,000 delayed candidates for CLIP and the first 3,000 for
|
||||
ALPHA. Later candidates for a list cannot be admitted even in an otherwise
|
||||
empty frame, so dropping only their prepared records is behavior-equivalent;
|
||||
their immediate duplicate, if any, still executes. Include this list in an
|
||||
explicit retained-byte/capacity diagnostic or an equivalent dedicated bound.
|
||||
After a rejection storm its count is zero at reset/next preparation and its
|
||||
retained capacity is no greater than the bounded geometric backing required
|
||||
for 6,000 records (8,192 with `List<T>` growth). Do not change either queue's
|
||||
3,000-entry capacity, FIFO append order, source registration, CLIP-then-ALPHA
|
||||
drain, router decisions, or row-5 immediate state.
|
||||
|
||||
Pins cover: more than 3,000 candidates for each list; accepted/rejected token
|
||||
counts; no rejected prepare/draw; flush, end, and abort cleanup; an injected
|
||||
immediate-draw exception after at least one delayed candidate; bounded count,
|
||||
capacity, and retained bytes; and the real warmed driver/particle/dispatcher
|
||||
merge at 0 managed bytes. Mutations restoring eager reservation, omitting
|
||||
false/exception rollback, or removing the per-list preparation cap must fail
|
||||
at their first named count/capacity assertion.
|
||||
|
||||
### 19.3 F3 — prose and register truth
|
||||
|
||||
Correct `WalkFrameDriver.cs`'s `WalkFrameStaticRecords` comment: records retain
|
||||
authored traversal/registration order until the ordinary-cell populator builds
|
||||
the combined static/dynamic part list and performs the retail per-cell CYpt
|
||||
sort. They are not final stream order. After F1, AP-241's positive authored-
|
||||
part-order claim becomes true; AP-241/AP-242/AP-243 otherwise remain unchanged,
|
||||
unique, inside the AP table, and the active physical count remains 162. No new
|
||||
deviation is introduced by this exact repair.
|
||||
|
||||
### 19.4 Scope, return, and review order
|
||||
|
||||
Production edits are limited to `ParticleRenderer.cs`,
|
||||
`ParticleSubmissionOrdering.cs`, and the comment-only correction in
|
||||
`Walk/WalkFrameDriver.cs`. Tests may change only
|
||||
`ParticleRendererRouteTests.cs` and `Walk/WalkFrameDriverTests.cs`; this packet
|
||||
records the result. If the implementer proves one additional existing test
|
||||
helper is the minimum real-path fixture seam, the lead must approve and record
|
||||
it before commit. No router, queue, pipeline, shader, manifest, Content model,
|
||||
serializer, package format, building-shell, EnvCell, or PView behavior changes.
|
||||
|
||||
Return one fix commit on top of `44e2bc227b`: `git diff --check`; Release 0W/0E;
|
||||
the focused particle/driver/queue/order/bounds suite; the real 0-B pin; shader
|
||||
contract lane; and a mutation ledger naming each actual first failure. No
|
||||
graphical launch. The retail lens re-reviews F1, the paired bytes, F3, and the
|
||||
unchanged S4-c2 behavior first. Only a retail PASS unlocks the sequential
|
||||
production/gate-honesty lens over the entire c3a stack, with special attention
|
||||
to F2. A failed re-review gets the one remaining bounded fix round; a further
|
||||
finding after that would require a third round and stops the chunk.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue