[MG_Backend] (P7): every silent exit on the Magma wire draw path has a name, a tally and a decline line

Rule I admits two shapes for a refusal on the wire arm, a decline and a named Fatal. The draw
path had a third one the rule does not allow: roughly forty bare `return false` statements with
no log, no counter and no census entry, so a dropped draw left no trace anywhere - which is how
the OpenRA device divergence survived four device windows with client and server logs that were
line-identical between a passing and a failing run.

WireDeclines.def names every one of them; WireDeclineTally.h expands that into a counter table
plus MGL_WIRE_DECLINE_AT (the tally always moves, the log is once per site), in the shape of
PipeApplier.h's ServerVerbSink tallies and for the same reason (R-16: a probe may not arm
against a stub). Covered: SetupWireDraw and DispatchWireCompute (25), the three exits of
PrepareWireTextureResources, the four of SyncTextureResourceByHandle, and UploadPendingWireLevels'
five false exits PLUS the two that only `continue` - those report SUCCESS while leaving the entry
pending, i.e. a draw that samples a level which was never uploaded, so they are counted apart.

Also the pending-upload gauges (entries, bytes, peak bytes), sampled at the funnel, because a
refused upload does not consume its entry and the level shadow behind it stays alive.

Shutdown dumps the tally and is silent when it is all zero: a green lane stays quiet and a lane
that dropped a draw cannot. Plus the drain probe behind MOBILEGL_MAGMA_WIREBUF_PROBE, which is
what measured that a host replay reaches the mid-frame frame-boundary drain zero times.
This commit is contained in:
2026-09-22 18:44:07 -04:00
parent b089e0de9b
commit 76bbb6c300
6 changed files with 405 additions and 31 deletions
@@ -33,6 +33,8 @@
#include <MG_Pipe/PipeApply.h>
// P7 wave 0: the seam WireDescriptorFatal dies through. See MG_Pipe/PipeSessionFail.h.
#include <MG_Pipe/PipeSessionFail.h>
// P7 wave 2 package B3: rule I's tally for this file's silent wire-draw exits.
#include "WireDeclineTally.h"
#endif
#include <vulkan/utility/vk_format_utils.h>
#include <algorithm>
@@ -2944,7 +2946,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool UniformManager::PrepareWireTextureResources(const MagmaProgramSource& program,
const ProgramFactory::VkProgramObject& programObj) {
if (!program.IsWire()) return true;
if (programObj.declinedDescriptors || m_textureManager == nullptr) return false;
if (programObj.declinedDescriptors || m_textureManager == nullptr) {
MGL_WIRE_DECLINE_AT(DescriptorDeclined, "the program carries a descriptor MobileGL could not resolve");
return false;
}
const auto& state = MG_Pipe::MGPipeApplier();
// Resolve writable images first: aliases sampled by the same draw must
// see the final STORAGE-capable allocation before any view is built.
@@ -2958,11 +2963,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
const Uint32 count = BindingDescriptorCount(programObj, binding);
for (Uint32 element = 0; element < count; ++element) {
const Int location = baseLocation + static_cast<Int>(element);
if (baseLocation < 0 || !program.UniformLocationsAliasSameUniform(baseLocation, location))
if (baseLocation < 0 || !program.UniformLocationsAliasSameUniform(baseLocation, location)) {
MGL_WIRE_DECLINE_AT(SamplerLocationAlias,
"binding %u element %u does not alias one sampler uniform", binding,
element);
return false;
}
const Int unit = program.GetUniformSamplerOrImageUnitIndex(static_cast<Uint>(location));
if (unit < 0 || static_cast<Uint32>(unit) >=
(storage ? MG_Pipe::kMGPipeMaxImageUnits : MG_Pipe::kMGPipeMaxTextureUnits)) return false;
(storage ? MG_Pipe::kMGPipeMaxImageUnits : MG_Pipe::kMGPipeMaxTextureUnits)) {
MGL_WIRE_DECLINE_AT(SamplerUnitRange, "sampler/image unit %d is out of range", unit);
return false;
}
const auto handle = storage ? state.BoundShaderImages[unit].Res
: state.BoundSamplerViews[unit].Texture;
// Null is the wire's unbound/incomplete binding. Its native