mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Set, count down and clear vk_dlaa.c's setting_presents with atomics, as vk_dlaa_frame and vk_dlaa_resized_take can run on two threads.
setting_presents says how many more presents a new scene size counts as the result of a settings change (the resize hold of vk_backend.c frame_hold). vk_dlaa_frame sets and counts it down, and vk_dlaa_resized_take tests and clears it at the same present. With the replay on the submitting threads the frame's bookkeeping, vk_dlaa_frame among it, can run on another thread than the presenting one (another thread's replay, or the next submission once the bookkeeping goes in replay order), so a plain test-then-clear beside a plain decrement could take the hold twice or miss it. Now the take is two exchanges, which give the outcome of the old two statements, and the count-down is a compare-and-swap that stops at 0, so it never goes below a clear made meanwhile. Not reproduced before the change. Checks that passed: pass_cc_check of vk_dlaa.c with no new -Wall -Wextra warnings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3244,15 +3244,16 @@ static void preset_check(void) {
|
||||
// intact (Ultra Performance and DLAA). Measured by capturing every present over six mode changes, 2026-11-10: bad
|
||||
// frames 3 and 5 presents after the change, with every other setting the same. evaluate notes a scene of another size;
|
||||
// vk_dlaa_frame counts the presents since a setting last changed, so a game that draws two sizes in turn holds nothing.
|
||||
static int setting_presents; // vk_dlaa_frame: presents left in which that counts as a mode change
|
||||
// setting_presents: presents left in which that counts as a mode change. vk_dlaa_frame sets and counts it down on the
|
||||
// thread that runs the frame's bookkeeping, vk_dlaa_resized_take clears it on the presenting thread: atomics.
|
||||
static int setting_presents;
|
||||
#define SETTING_PRESENTS 60
|
||||
|
||||
// vk_backend.c frame_hold, each present after vk_dlaa_frame: 1 once when the scene took a new size after a setting
|
||||
// changed. The previous picture then stays on screen over the frames described above.
|
||||
int vk_dlaa_resized_take(void) {
|
||||
if (!__atomic_exchange_n(&size_changed, 0, __ATOMIC_ACQ_REL) || !setting_presents) return 0;
|
||||
setting_presents = 0;
|
||||
return 1;
|
||||
if (!__atomic_exchange_n(&size_changed, 0, __ATOMIC_ACQ_REL)) return 0;
|
||||
return __atomic_exchange_n(&setting_presents, 0, __ATOMIC_ACQ_REL) != 0;
|
||||
}
|
||||
|
||||
// What DLSS holds while nothing uses it (NX2NAVI_DLSS_IDLE_FREE 1 or 2, the default 1). With the upscaler switched off
|
||||
@@ -3423,8 +3424,13 @@ void vk_dlaa_frame(void) {
|
||||
static int cfg_known;
|
||||
unsigned v = cfg_version();
|
||||
D.presents++;
|
||||
if (cfg_known && v != cfg_seen) setting_presents = SETTING_PRESENTS;
|
||||
else if (setting_presents) setting_presents--;
|
||||
if (cfg_known && v != cfg_seen) {
|
||||
__atomic_store_n(&setting_presents, SETTING_PRESENTS, __ATOMIC_RELAXED);
|
||||
} else { // down to 0, not past it: vk_dlaa_resized_take may clear it meanwhile
|
||||
int s = __atomic_load_n(&setting_presents, __ATOMIC_RELAXED);
|
||||
while (s > 0 &&
|
||||
!__atomic_compare_exchange_n(&setting_presents, &s, s - 1, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) {}
|
||||
}
|
||||
cfg_seen = v, cfg_known = 1;
|
||||
vk_dlaa_swap_img = NULL, vk_dlaa_swap_view = VK_NULL_HANDLE;
|
||||
D.pre = D.comp = 0, D.comp_game = VK_NULL_HANDLE; // the frame before was recorded up to its present
|
||||
|
||||
Reference in New Issue
Block a user