Skip to content

GPU commands run one after another, each draw with frozen settings

In plain words

A program's command list mixes settings changes, draws, constant updates, clears and "tell the CPU I'm done" signals. Their order matters, but the PC's graphics card runs on its own clock. So we process a whole command list before returning. Every draw gets a frozen copy of its settings, everything runs in list order, and the results are in emulated RAM when the call returns. It is like a cashier who rings up each item before taking the next: slower than a busy kitchen, but never out of order.

Context and Problem Statement

A pushbuffer, the program's command list, interleaves state writes, draws, constant buffer updates, clears and semaphore releases, the GPU's "got this far" signals. The order they take effect in matters, and a host GPU queue runs on its own clock. Nintendo's OS would wait on fences, the host's done-flags, or syncpoints, the Switch's hardware counters; Kokoromi does not emulate that OS.

Decision Outcome

Pusher::submit reads the GPFIFO, the queue of command lists, to the end and returns an ordered list of events. The 3D class keeps the raw register words. At each draw it copies what that draw needs into a frozen DrawSnapshot.

LOAD_CONSTANT_BUFFER, which updates a constant table, is an event in the same list. So are compute launches, clears, reports, semaphore releases and acquires. They therefore apply in command order.

The engine runs each event before the next, and Gpu::submit returns once every draw is back in emulated RAM. An acquire must already be met when it is reached, since nothing else runs that could release it. There are no macros (MME) yet, and no overlap of GPU work.

What this makes easy

  • Ordering is right by construction, and tests can read results straight after submit.
  • The command reader and the 3D class are plain data code, tested without a graphics card.

What this makes hard

  • The CPU waits for the GPU on every submit, so real games will need the game's done-signals decoupled from the host's.
  • An acquire that waits for a later release fails instead of waiting.
  • Command lists that use macros fail until the GPU's macro processor, MME64, is emulated.

Confirmation

core/src/tests/gpu/fifo.rs for decoding and ordering, and the engine tests for report sizes, semaphore values and acquires in emulated RAM.

Sources: core/src/gpu/fifo.rs, core/src/gpu/threed.rs, core/src/gpu/engine.rs.