D876 - Memory a queued submission writes is read once it has been carried out
Status: decided Date: 2026-10-14
Amends D874. What a preparation read waits for is everything a queued
submission writes, not only the colour targets it draws into: the
command processor's own WRITE_DATA to memory,
DMA_DATA fills and copies and value-storing
RELEASE_MEM (cp::written_spans, from the
packet walk), and each compute dispatch's buffers and window
(Pipeline::dispatch_write_spans, from its state and
bindings, without translating or running it). The queue keeps these
spans beside the drawn targets. A submission whose writes cannot be
bounded before it runs - a dispatch whose state the registers do not
give, whose program does not decode or trace, or that stores other than
through a buffer (an image, a global or flat address), or a draw that
streams out (D861) - is queued as writing everything, and every
preparation read waits for it.
The spans are worked out on the guest's thread as the submission is
queued, and only asynchronously: each dispatch's state and whether any
draw streams out ride on the Submission from its
preparation, and the dispatch's program is decoded and its buffers
traced again there.
A read inside a preparation no longer waits where it is. The
preparation holds the live pipeline, and the command processor carries a
dispatch or a run of draws out through that same pipeline, so the wait
D874 put in the read could only time out, ten seconds later, and read
what it would have read anyway. The read is noted instead; the
preparation finishes, the pipeline is released, the queued submissions
up to the latest one that writes over a read are carried out - those
queued after it are not waited for - and the submission is prepared
again (command_processor::preparing), up to three times,
since another guest thread can queue in between. Preparing a stream
again gives the same submission: its registers come from the state
carried in, which only carry_registers advances, after the
preparation that is kept.
Preparation stays on the guest's thread: moving it to the command processor's was measured about 20% slower (D874).
Why: a later submission's preparation reads texels,
descriptor tables, buffers and shader code through
SettledReads, and the command processor's thread is the
only one that carries out a queued submission's packets and dispatches.
Prepared ahead of them, a texture a dispatch stores to, a buffer a
DMA_DATA copies into, or a table a WRITE_DATA
patches was read as it stood before. The test
a_preparation_reading_what_a_queued_submission_writes_is_made_again_after_it
holds the processor off and checks that a preparation reading a queued
write is made again, and returns only once the write has been carried
out; a_stream_writes_where_its_packets_land checks the
spans.
Not covered: a depth or stencil target a queued submission draws into, and memory written by packets the command processor here does not carry out (they stop the queue, D710), are still read as they stood before the submission. The spans a dispatch writes are every byte of each buffer it stores through and of its window where it stores through that (D882), not only the bytes it stores, so a read of a part of one it leaves alone still waits.