Configuration

Everything is an environment variable, set per game (Steam launch options) or in the shell. The names mirror the settings AMD exposes for AFMF on Windows where such a setting exists.

Variable Default Meaning
AFMF_ENABLE unset 1 loads the layer
DISABLE_AFMF unset 1 keeps it out even when enabled
AFMF_LOG 0 0 errors, 1 warnings, 2 info, 3 debug, all on stderr
AFMF_PERFORMANCE_MODE auto auto: performance from 2560x1440 up, quality below. quality: optical flow at display resolution (8 px blocks). performance: at half resolution (16 px blocks)
AFMF_SEARCH_MODE auto auto: 7 pyramid levels at full flow resolution, 5 at half (+-256 px of motion on screen). standard: 5 levels. high: 7 levels always, motion up to +-512 flow pixels
AFMF_FAST_MOTION_RESPONSE blend What to show where the flow is unreliable: repeat the previous frame, or blend both
AFMF_GAMESCOPE unset 1 when the game runs under Gamescope (Steam Deck, or gamescope -- <game>): five extra images instead of two, and the layer passes through in the gamescope process itself
AFMF_EXTRA_IMAGES 2 (5 with AFMF_GAMESCOPE=1) Swapchain images added beyond what the application asked for (1..8). Fewer means more presents without a companion; more means more memory; some engines abort above 8 images in total (id Tech 8)
AFMF_ACQUIRE_TIMEOUT_US 0 Longest the layer waits for the companion’s image to be released before presenting the real frame alone. The image is requested a frame ahead, so the default never stalls the game
AFMF_PRESENT_MODE auto auto: a swapchain the game creates in FIFO (vsync) is created in MAILBOX when the surface offers it, and a per-present switch back to FIFO is rewritten too. In FIFO every present takes a refresh slot and the layer doubles them, so a game above half the refresh rate loses real frames (120 at 165 Hz becomes 82); MAILBOX shows the latest frame and drops the excess. keep leaves the game’s mode alone
AFMF_ASYNC 1 0 runs the work on the application’s queue and presents inline (diagnosis)
AFMF_PACING 1 0 presents the real frame right behind the generated one instead of half a frame later: uneven cadence, the compositor may drop generated frames
AFMF_GOVERNOR 1 1 steps generation down while the GPU is contended (the generated frame ready later than a frame and a half, thirty frames in a row): five search levels first, then one companion in two, then one in three; back up a step after 15 frames ready within three quarters of a frame. Off, every frame gets a companion regardless
AFMF_MIN_FPS 30 Below this real frame rate no companion is made: doubling 25 fps is not worth its latency. Generation returns once the rate is a tenth above the floor, so a game sitting on it does not flicker between the two. 0 removes the floor
AFMF_STATIC_BLOCK_SAD 128 A block whose 64 pixels differ from the previous frame’s at rest by no more than this (sum of absolute 8-bit luma differences) is static: vector 0, search skipped. 0 searches every block
AFMF_DIRECT_INGEST 1 The game’s frame is read once, straight from its swapchain image, into the layer’s colour ring and the flow’s luma. Puts sampled usage on the game’s swapchain images; 0 puts the copy back. Not for sRGB swapchains (the copy path stays there)
AFMF_SAD_INT16 1 The block search sums its pixel differences on packed 16-bit pairs (two per instruction; needs shaderInt16, which the layer enables on the device when the game did not). 0 keeps the SDK’s byte-at-a-time sum
AFMF_DIRECT_OUTPUT 0 1 writes the interpolated frame straight into the swapchain image instead of copying it there (saves the copy, 44-59 us at 3440x1440), which puts storage usage on the game’s swapchain images; that can cost the game’s own rendering more than it saves, so measure it per game. Needs a format that takes storage writes (not sRGB)
AFMF_HUD_DETECT 1 A pixel that is the same in both frames (within one 8-bit level) while its block moves is a static overlay (HUD, crosshair, subtitles): it is kept instead of warped. 0 warps everything
AFMF_INTERPOLATE 1 0 repeats the previous frame instead of interpolating (debug)
AFMF_PROFILE 0 1 logs GPU time per stage and host time per present every 300 frames and at teardown
AFMF_DUMP_DIR unset Writes four generated frames into that directory, created if it does not exist: afmf_generated_<frame>.ppm with the block flow that made it as afmf_flow_<frame>.txt (vx vy per block, prev = cur + v), and a log line with the luma and flow statistics. They are the companions of real frames 8-11, before which the scene change detector is still warming up, which in most games is a loading screen: touch <dir>/dump-now while playing writes another four from what is on screen at that moment, as often as you like. 8- and 10-bit swapchains; a format that cannot be dumped is named in the log

Presets

Default: AFMF_ENABLE=1. The flow runs at half resolution from 1440p up, which is where a game is most likely to be saturating the GPU already.

Every pixel of the flow, at about a quarter more GPU cost per generated frame: AFMF_ENABLE=1 AFMF_PERFORMANCE_MODE=quality AFMF_SEARCH_MODE=high.

Without pacing (uneven cadence, the compositor may drop generated frames above the refresh rate): add AFMF_PACING=0.

Under Gamescope (Steam Deck, or nested on the desktop): AFMF_ENABLE=1 AFMF_GAMESCOPE=1, on the gamescope command line or in the Steam launch options; see the FAQ.

Diagnosis: add AFMF_LOG=2 AFMF_PROFILE=1 and 2>afmf.log after %command%; attach the file to a bug report.

Reading the log

[AFMF info] device 0x... created, VK_KHR_swapchain enabled, no spare compute queue: sharing the application's queue 3 of family 1
[AFMF info] surface 0x... created: Wayland
[AFMF info] interpolation ready: 3440x1440, flow at 1720x720 (215x90 blocks of 16 px), 5 pyramid levels
[AFMF info] swapchain 0x... created: 3440x1440, format 37, present mode 1 (app asked 2), 5 images (app asked 3), generation on (layer queue)
[AFMF info] swapchain 0x...: 3001 presents, 2999 generated, 0 no free image; 8.05 ms between presents (124 real fps); in the hook 31 us per present; work thread: slot fence 2, acquire 3, record 41, submit 35; presentation thread: present generated 279, present real 252, refill 29, gpu done +0.41 ms, pacing hold 4.53 ms; governor step 0
[AFMF info] swapchain 0x... destroyed after 26381 presents: 26380 generated, 1 skipped (0 no free image, 1 no history, 0 held back by the governor)