Skip to content

afmf-linux v1.0.0

Choose a tag to compare

@github-actions github-actions released this 16 Sep 03:07
· 44 commits to main since this release
v1.0.0
a0820b5

Added

  • AFMF_PRESENT_MODE (auto): a swapchain created in FIFO is created in MAILBOX when the surface
    offers it, the allowed per-present modes (VK_EXT_swapchain_maintenance1) get MAILBOX added,
    and a per-present switch back to FIFO is rewritten. In FIFO the doubled presents each took a
    refresh slot: vkcube at 165 Hz got 2 companions in 1196 presents, now 595 in 596. keep
    leaves the game's mode alone.
  • AFMF_STATIC_BLOCK_SAD (128): the block search skips blocks that did not change between the
    two frames (their SAD at rest, which the SDK already computed for its level-0 fallback, is taken
    first); still parts of the picture cost nothing to search. One marked edit in the vendored
    search shader, listed in shaders/fidelityfx/NOTICE.md.
  • The scene change detector's histogram runs alongside the luma pyramid and its divergence
    alongside the coarsest search, with no barrier in between (both only read the level-0 luma;
    the coarsest search reads the detector's output without waiting, which every finer level and
    the interpolator still do), and the block search checks a group's four predictions at once
    before any of them searches.
  • AFMF_SAD_INT16 (on): the block search's sum of absolute differences runs on packed 16-bit
    byte pairs (v_pk_* on RDNA) instead of one byte at a time, from a second build of the SDK's
    search pass; the layer enables shaderInt16 at device creation when the game did not and the
    device offers it. Test headless_pan_scalar_sad checks the SDK's sum gives the same field.
  • AFMF_DIRECT_INGEST (on): the game's frame is read once, from its swapchain image, into the
    colour ring and the flow's luma by one pass, instead of copied and then read again by the
    SDK's luma pass. Not on sRGB swapchains.
  • AFMF_DIRECT_OUTPUT (off): the interpolator writes the swapchain image itself instead of an
    internal image copied there; opt-in because it needs storage usage on the game's swapchain
    images, whose cost to the game's rendering only a game measurement can tell. Test
    headless_direct_output.
  • AFMF_HUD_DETECT (on): a pixel unchanged between the two frames on a moving block is kept as
    it is instead of warped, so a HUD, crosshair or subtitle over motion stays whole in the
    generated frame. Tests headless_hud and its negative control headless_hud_negative.
  • Defaults now aim at quality: flow at display resolution with all seven pyramid levels
    (AFMF_PERFORMANCE_MODE=quality, AFMF_SEARCH_MODE=high), AFMF_FAST_MOTION_RESPONSE=blend,
    AFMF_LOG=0. The block search skips every block whose vector from the coarser level already
    matches (AFMF_STATIC_BLOCK_SAD), which is what keeps the cost of the full search near the
    previous release's half-resolution one.
  • AFMF_GOVERNOR (on by default): under GPU contention, when the generated frame is ready later
    than a frame and a half thirty frames in a row, generation steps down (five search levels, then
    one companion in two, then one in three) and steps back up after 15 frames ready within three
    quarters of a frame; each step is logged. AFMF_MIN_FPS (30): no companions below that real frame rate.
  • Present ids (VK_KHR_present_id and present_id2, what DXVK attaches) are carried on the real
    frame by the presentation thread instead of forcing the present inline; tests headless_present_id1
    and headless_present_id2.

Changed

  • The present hook no longer records or submits: it consumes the game's wait semaphores with
    an empty submission (they must be waited before the game signals them again) and queues the
    frame to a work thread, which waits the slot, takes the companion's image, records, submits and
    hands the presents to the presentation thread. The profile line splits the three: in the hook, work thread, presentation thread. Test headless_async_drain destroys the swapchain
    with frames still in both threads.
  • The layer's pipelines compile on a thread of their own from vkCreateDevice; the first
    swapchain only waits for what is left instead of compiling everything on the first present.
  • The optical flow and the interpolation are recorded once per (slot, parity, companion) into
    secondary command buffers and executed from then on; the per-frame primary keeps only the
    copies from and to the swapchain images. Host time recording a frame in the present hook:
    170-190 us to 80-117 us in the headless test under the validation layer.
  • Pacing measures the half-frame hold from the moment the generated frame is ready on the GPU, not
    from the present call, capped at one frame after it; the profile line shows the delay as gpu done.

Fixed

  • The headless golden test looked at the companions of real frames 1 and 2, which the optical
    flow's scene change detector zeroes during its six-frame warm-up: what it measured was a
    motionless blend of the two frames, whose centre is the same. Dumps now start at frame 8 and
    the test also checks the flow vectors on the square (afmf_flow_<frame>.txt); a failed check
    now fails the test (FAIL_REGULAR_EXPRESSION matched a ^ that CMake does not treat as a
    line start).
  • The application's vkGetSwapchainImagesKHR is serialised with the presentation thread's presents
    (a thread-safety validation error when both ran at once).
  • The presentation thread could starve on the swapchain lock behind an application spinning in
    vkAcquireNextImageKHR (a glibc mutex is not fair): presents stalled for seconds and no image
    ever came free. The lock is now taken in turn, and the spare's release fence is waited on outside
    it.
  • The pacing hold ends when the next real frame arrives, and a single hitch (a 100 ms frame) no
    longer inflates the frame-time estimate: after one, the real frames were held up to 20 ms each,
    images ran out and AFMF_MIN_FPS withheld companions for a while.
  • AFMF_ACQUIRE_TIMEOUT_US also bounds the acquire of the companion's image, not only its release
    fence; frames withheld by AFMF_MIN_FPS are counted in the swapchain's report.