D551 - The export was already decoded, and its blocker had half expired
decided - 2026-09-04
The plan named G11 step (a) - "solve the export's operand layout by probe" - as the next capture-free item. It has been done for some time.
Checked by decoding, not by reading the table
opcode-operands.toml carries an EXP entry solved from
ten samples. That is the table saying so; the decoder saying so is a
different claim, and it is the one that matters:
0xF8000000 | (target << 4), second word 0x03020100
target=0 Immediate(0) Vector(0) Vector(1) Vector(2) Vector(3)
target=1 Immediate(1) Vector(0) Vector(1) Vector(2) Vector(3)
target=12 Immediate(12) Vector(0) Vector(1) Vector(2) Vector(3)
operands_decoded is true, which is separately
meaningful: an empty operand list with that flag set means the family
genuinely takes none, and without it means nobody has taught the decoder
the family. The decoder is careful about the difference and this checks
the right one.
Nothing asserted any of it, which is how it stayed
listed as work. tests/export_decode.rs now does - the
assertion that was missing, not a new capability.
Broken twice, and the second break is the interesting one. Deleting
the EXP entry fails on operands_decoded. Moving the target
field one bit across leaves target 0 decoding as zero
and fails only on target 1: a test that used mrt0
alone would have passed a wrong field position. Three targets,
three answers, for the same reason the framebuffer harness checks every
pixel.
The blocker had half expired
orbistoun-translate's BLOCKED entry for
exp read:
exporting needs a render target to export to, and there is no concept of one yet - every translated module today is a compute dispatch writing to a storage buffer…
The first clause stopped being true two ticks ago. There is a concept
of a render target: a colour attachment, a render pass, a graphics
pipeline, and a fragment shader's Location 0 output
reaching attachment zero - proved on a device by
orbistoun-gpu-vulkan/tests/draw.rs (D549, D550).
BLOCKED is not decoration. Its whole purpose is to
separate "nobody has looked at this" from "this is waiting
on a subsystem", because those rank differently and a list that
cannot tell them apart sends effort at whichever is most frequent. An
entry claiming a whole missing subsystem, when what is actually missing
is one execution model, ranks itself far too heavily.
Rewritten to say the one thing that is still true: every
module this translator emits is a compute dispatch, so an export has
nowhere to go inside it. A Fragment execution
model with output variables is the missing piece.
The clause that survives untouched is the one that matters most: mapping the export onto the storage buffer instead would still be inventing a destination, and a shader that appears to work while writing its colour somewhere arbitrary is worse than one that refuses.
Three in three ticks, in three different files
D543 found a stated blocker wrong about its mechanism. D546 found one right about its mechanism and in the wrong list. This one had a reason that expired underneath it because the tick that invalidated it was my own, two ticks earlier, and nothing connected the two.
That is the sharpest version of the pattern so far. The other two were written by somebody who then stopped looking; this one was written before a change I made, and I did not go back. Check 13 exists for exactly this - when a change closes a gap, grep for the gap's own words - and what it needs is for the words to be searched at the moment the gap closes, not two ticks later when something else happens to walk past.
What is left of the export
One thing that needs nobody: emit Fragment modules with
output variables. One thing that needs a capture: which attachment a
target index selects, and what targets above the render-target range
mean - the mapping D104 refuses to invent, and which decoding does not
settle.