Files
NX2navi/runtime/mesh_fb_hold.h
chrg6 6e57ef9619 Check three of this pass's decisions without a device: the automatic texture detail, the device made with DLSS Frame Generation on, and the mesh fallback's depth hold.
Each decision moves into a header the runtime and a test both read, as vk_mesh_path.h does: vk_tex_detail.h (tex_detail_auto), vk_dlssg_device.h (dlssg_card_skipped, dlssg_device_create) and mesh_fb_hold.h (the hold's table). The runtime's behaviour is the same as before the move.

tests/tex_detail_check has the budgets from players' logs of 0.10.1 (a handheld's integrated GPU at 10,361 MiB now gets reduced, a 12 GiB card at 11,313 MiB full). tests/dlssg_device_check plays the laptop of the report with stand-ins for the interposer and the loader: the chosen Intel card is skipped, the NVIDIA card is made through the interposer, a card of another vendor is made by the loader without the interposer being asked, and a refusal falls through to the loader. tests/mesh_fb_hold_check holds a list for two presents after its colour draw was skipped, through a wait of 600 frames, and no longer once it is drawn or gone. Built against the rule 0.10.1 had, the first two and mesh_path_check fail (6, 13 and 3 checks).

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-14 05:35:49 -05:00

32 lines
1.9 KiB
C

// The mesh fallback's depth hold (vk_exec_draw.c "a list's depth-only draw is held"): which lists' colour draws were
// skipped lately. Header only, so that tests/mesh_fb_hold_check.c checks the table without a device.
//
// A list is its indirect record's address in the game's memory (below 2^39). One word per slot: the address above
// MFB_HOLD_BITS bits of the present count. The colour draw stamps its list with the present it was skipped in and
// clears the stamp when it is drawn; the list is held while the stamp is at most MFB_HOLD_PRESENTS presents old.
// Read and written by the replay's threads without a lock: a lost update costs a list one frame of the hold, and two
// lists in one slot (MFB_HOLD_SLOTS of them, by a hash of the address) hold only the one stamped last.
#pragma once
#include <stdint.h>
#define MFB_HOLD_SLOTS 1024
#define MFB_HOLD_PRESENTS 2
#define MFB_HOLD_BITS 24
#define MFB_HOLD_MASK ((1ull << MFB_HOLD_BITS) - 1)
static inline uint32_t mfb_hold_index(uint64_t list) { return (uint32_t)((list >> 2) * 0x9e3779b1u) >> 22; }
// The list's colour draw was skipped for its modules or pipeline (waits 1) at this present, or was drawn (0).
static inline void mfb_hold_mark(volatile uint64_t *tab, uint64_t list, int waits, uint64_t present) {
volatile uint64_t *slot = &tab[mfb_hold_index(list)];
if (waits) __atomic_store_n(slot, list << MFB_HOLD_BITS | (present & MFB_HOLD_MASK), __ATOMIC_RELAXED);
else if (__atomic_load_n(slot, __ATOMIC_RELAXED) >> MFB_HOLD_BITS == list) __atomic_store_n(slot, 0, __ATOMIC_RELAXED);
}
// Whether the list's depth-only draw is held at this present.
static inline int mfb_hold_test(const volatile uint64_t *tab, uint64_t list, uint64_t present) {
uint64_t w = __atomic_load_n(&tab[mfb_hold_index(list)], __ATOMIC_RELAXED);
if (!w || w >> MFB_HOLD_BITS != list) return 0;
return ((present - w) & MFB_HOLD_MASK) <= MFB_HOLD_PRESENTS;
}