D145 - Wavefront width is a parameter, and a narrow shader is a different instruction stream
Status: decided (executed on hardware)
D141 established that this generation runs shaders at either width, chosen per shader when it is compiled, and that the encodings are identical either way - so the tables needed no change. What it did not say is what the translator needs, which turned out to be more than a lane count.
A 32-lane shader manipulates its masks with the 32-bit scalar
instructions. Its mask is thirty-two bits and fits in one
register, so it writes s_mov_b32 exec_lo, 0 where a 64-lane
shader writes s_mov_b64 exec, 0, and narrows with
s_and_b32 exec_lo, exec_lo, sN. Those were being translated
as ordinary scalar writes into the register file - so the mask never
changed, every lane stayed active for the whole shader, and the result
was a shader that runs and is not the one the guest wrote. That is the
failure mode this project cares most about, and it was one line from
happening silently.
Masks are now written through the mask whenever the destination names one, at either width, and a mask read as a 32-bit source returns its low half instead of being refused for not being an inline float.
The width is supplied, not inferred.
Strategy::Predicated carries a Width,
defaulting to 64. Nothing in the instruction stream states the width,
and inferring it from which mask instructions appear would mean guessing
from an absence for any shader whose masks are untouched at the point of
the guess. On a real target it comes from the pipeline state the guest
set up; here it comes from the caller.
Not derived from a capture. No capture contains a narrow shader yet, so these are built the way the reference says a compiler would build them. What the tests verify is that the translator does the right thing given such a shader - not that this is what one looks like in the wild. Stated here rather than left to be discovered.