Two routes to a shader, because the loader thread named the entry points

The loader thread identified the guest's graphics entry points: the two command-buffer submit calls, and a vocabulary of the calls that build those buffers. The submit calls answer where to hook. The builder calls changed a design assumption, which is the more useful half.

The names show a command-buffer builder library - calls that append packets to a buffer the guest owns, and a separate call that submits it. So a shader can be learned about twice: once because the guest registered it, and once because a register write in the submitted packets points at it. Pipeline::submit now takes both, believes registration where they overlap, and counts every overlap either way.

That counting is the point. The register vocabulary is the least verified thing in this crate - its own data file says so - and nothing in this subsystem could produce evidence about it. Agreement between the two routes is evidence it is right; disagreement names both addresses and says it is wrong. Neither is obtainable without running both routes on the same submission, which is why the inferred path keeps running after registration has already answered.

A submission now also knows which queue it came from, and a stage that queue cannot run is reported rather than filtered - a vertex shader in a compute submission is a decode that found the wrong bits, not an unusual frame.

Surprises.

What this makes possible next. The same shape extends to the builder calls generally: hook one, record its arguments, decode the packets it just appended, and check the two agree. That would turn the packet vocabulary from transcribed-and-unverified into something differentially tested - the same move that found a wrong row in the shader encoding table. It needs captures, which is the other thread's side.