fix(render): interior shell and detail passes bind their own instance opacity (Campaign VM VM1)
EnvCellRenderer.Rhi's SubmitRhi bound StorageInstances/StorageBatches/ StorageClipSlots/StorageGlobalLights/StorageInstanceLightSets every frame but never GpuBindingModel.StorageInstanceAlpha (binding 7) — the SSBO mesh_modern.vert reads as instanceAlpha[instanceIndex] (vOpacityMultiplier, #188) and, as of Campaign VM VM1 (05970306), mesh_detail.vert now reads the same way (vDetailOpacity). Without a bind of its own, both the interior shell pass and the interior detail replay read whatever section WbDrawDispatcher's own SubmitRhi last bound in the same pass — an unrelated object's opacity array, indexed by these EnvCell instance ids. This predates VM1 (6c79d35chas the same omission on the mesh_modern side); VM1 must not widen a latent defect by adding a second unconditional reader of the same unbound slot. Fix, root cause, no guard: EnvCellRenderer now owns _instanceAlphaData, a grow-only float[] parallel to _gpuInstanceTransforms (same pattern as _clipSlotData/_lightSetData), filled with the constant 1.0f every frame — EnvCell shells have no #188 TransparentPartHook translucency fade (that mechanism fades object PARTS, never cells) — and bound at GpuBindingModel.StorageInstanceAlpha alongside the renderer's other per-frame ring sections, before any draw in the pass. Test: EnvCellRendererTests.SubmitRhi_BindsConstantOneInstanceAlphaBeforeAnyDrawInThePass drives SubmitRhi directly (reflection, mirroring the file's existing private-method test pattern) with N seeded cell instances and one real draw command, then asserts against RecordingGpuDevice that StorageInstanceAlpha is bound with exactly N floats all equal to 1.0f, and that the bind precedes the pass's first MultiDrawIndexedIndirect call. Verified failing (StorageInstanceAlpha was never bound) with the fix temporarily reverted, then passing restored. Verified: dotnet build AcDream.slnx -c Release (0 warnings, 0 errors); dotnet test on AcDream.App.Tests (Release, hermetic lanes) green, 5960/5960 (5959 baseline + 1 new test). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
059703066f
commit
388457a735
3 changed files with 147 additions and 0 deletions
|
|
@ -82,6 +82,18 @@ public sealed partial class EnvCellRenderer :
|
|||
// slot 0 ⇒ no-clip.
|
||||
private uint[] _clipSlotData = Array.Empty<uint>();
|
||||
|
||||
// Campaign VM VM1 follow-up: per-instance opacity multiplier, parallel to
|
||||
// _gpuInstanceTransforms, feeding mesh_modern.vert/mesh_detail.vert's
|
||||
// InstanceAlphaBuf (binding 7, GpuBindingModel.StorageInstanceAlpha).
|
||||
// Before this field the shell and interior-detail passes never bound that
|
||||
// storage buffer at all, so both shaders read whatever section
|
||||
// WbDrawDispatcher's own SubmitRhi last bound in the same pass — an
|
||||
// unrelated object's opacity array, indexed by these cell instance ids.
|
||||
// EnvCell shells never carry a #188 TransparentPartHook translucency fade
|
||||
// (that mechanism fades object PARTS, never cells), so every element is
|
||||
// the constant no-op 1.0f.
|
||||
private float[] _instanceAlphaData = Array.Empty<float>();
|
||||
|
||||
// A7 Fix D (D-2): this renderer owns its lighting (self-contained state,
|
||||
// like uViewProjection) instead of reading whatever WbDrawDispatcher last
|
||||
// bound. Global point-light snapshot (same data/indices as the dispatcher,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue