Let the Anti-aliasing row's Game SMAA, Off, FXAA and SMAA run together with FSR 4, FSR 3.1 or DLSS, and show the anti-aliasing in the performance overlay.

Choosing one of them while a temporal upscaler was set turned the upscaler off, and the picture fell back to bilinear scaling. vk_aa.c no longer keeps the game's SMAA while DLSS or FSR runs. The chosen pass replaces the game's composition as without them: in the native modes after the upscaler, and in the scaling modes before it. In the menu, a choice leaves the upscaler and frame generation alone, and the row notes that the upscaler's TAA runs too. Picking DLSS or FSR under Upscaling keeps the Anti-aliasing choice. The TAA entry, listed while no temporal mode is set, now sets FSR 4 Native AA where FSR 4 runs instead of forcing FSR 3.1. The overlay gets an Anti-aliasing line under Upscaling, for example "TAA + SMAA (Ultra)".

Checked on an RX 7900 XT in Hyrule Field with FSR 4.1 Native AA and Quality, and with FSR 3.1. The log has "the game's SMAA replaced by" smaa, off and fxaa while FSR 4.1.2 upscales, and the pictures are right.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
epicmeme546
2026-11-12 08:23:14 -05:00
parent 89c453d7bb
commit 1c654ba0c1
9 changed files with 109 additions and 65 deletions

View File

@@ -195,7 +195,9 @@ keeps per-core data without locks and relies on that, so the host models it (`ru
composite (edges, blending weights, composition into the scene target as square-rooted RGB9E5 words). `off`, `fxaa`
and `smaa` leave out the first two and replace the composition with `shaders/aa_post.comp` or SMAA at its Ultra preset
(`shaders/smaa_*.comp`); the game's passes are known by a hash of their guest code (`vk_exec_draw.c` `aa_dispatch`).
`taa` is DLSS or FSR 3.1 at the scene's size; while either runs, the game's SMAA stays.
`taa` is DLSS or FSR at the scene's size with the game's SMAA. While DLSS or FSR runs (`dlaa`, any mode), the other
values still choose the pass: in the native modes it smooths the upscaler's picture after the bloom, in the scaling
modes it runs on the scene before the upscaler scales it.
- HDR (`vk_hdr.c`): the game tonemaps its scene into a float target, upscales it, draws the HUD into a second float
target and copies that into the 8-bit sRGB window texture it presents. With `NX2NAVI_HDR=1` the tonemap shader gets
the function of `shaders/hdr_tonemap.frag` spliced in where its SDR curve clamps each channel, so the float picture

10
docs/releases/v0.9.1.md Normal file
View File

@@ -0,0 +1,10 @@
## Changed
- **The Anti-aliasing setting works with FSR 4, FSR 3.1 and DLSS.** Choosing Game SMAA, Off, FXAA or SMAA (Ultra) with
one of them on under Upscaling used to switch the upscaler off and leave the picture to bilinear scaling. Now the
upscaler stays, its TAA keeps running, and the chosen pass runs along with it (the row says "plus TAA from
Upscaling"): *Off* leaves the edges to the TAA alone, *SMAA (Ultra)* smooths what the TAA leaves. Picking FSR or DLSS
under Upscaling keeps the Anti-aliasing choice too, and the row's TAA entry now sets FSR 4 where it runs, no longer
FSR 3.1 in its place.
- **The performance overlay shows the anti-aliasing** under Upscaling, as *TAA + SMAA (Ultra)* and the like while FSR
or DLSS runs.

View File

@@ -500,9 +500,10 @@
# more of the trails and leaves those edges a little less smooth. Changes while the game runs take effect at once.
# dlss_char_mask = 65
# Anti-aliasing of the 3D picture: game (the game's own SMAA, as on the console), off, fxaa, smaa (SMAA at its Ultra
# preset in the game's place) or taa (DLSS or FSR 3.1 at full size: dlaa = 1 with dlss = dlaa, which the menu's
# Anti-aliasing row sets with it). While DLSS or FSR 3.1 runs, the game's SMAA stays whatever this says. Changes while
# the game runs take effect at once.
# preset in the game's place) or taa (DLSS or FSR at full size: dlaa = 1 with dlss = dlaa, which the menu's
# Anti-aliasing row sets with it, and the game's SMAA). With DLSS or FSR on (dlaa = 1, any mode) their TAA always runs,
# and game, off, fxaa or smaa runs along with it: off leaves the edges to the TAA alone. Changes while the game runs
# take effect at once.
# aa = game
# The FXAA switch of the game this runtime was first written for; Ocarina has no such pass, so it changes nothing here
# (aa above is the setting).

View File

@@ -923,6 +923,21 @@ static void upscaling_name(char *out, size_t size) {
else snprintf(out, size, mode ? "DLSS %s" : "NVIDIA %s", menu_text(dlss[mode]));
}
// The Anti-aliasing row's value for the performance overlay: what row_aa shows, with "TAA + " before it while DLSS's or
// FSR's TAA runs with it (as upscaling_name tells it: FSR 3.1 set where it cannot load runs nothing), and TAA alone
// for off then.
static void aa_name(char *out, size_t size) {
static const char *const values[] = {"game", "off", "fxaa", "smaa"};
static const UiTextId names[] = {UI_MENU_AA_GAME, UI_MENU_FRAMEGEN_OFF, UI_MENU_AA_FXAA, UI_MENU_AA_SMAA};
int i = 0;
for (int k = 0; k < 4; k++)
if (!strcmp(cfg_value("NX2NAVI_AA"), values[k])) i = k; // taa: the game's SMAA, with the upscaler or alone
const bool taa = cfg_bool("NX2NAVI_DLAA") && (strcmp(cfg_value("NX2NAVI_TAA"), "fsr3") || vk_ffx_available());
if (taa && i == 1) snprintf(out, size, "TAA");
else if (taa) snprintf(out, size, "TAA + %s", menu_text(names[i]));
else snprintf(out, size, "%s", menu_text(names[i]));
}
// The Upscaling row's NVIDIA DLSS waits for a restart (vk_dlaa_needs_restart), where DLSS is offered: the row's note and
// the Restart button's count (restart_pending).
static bool upscaling_restart(void) { return dlss_offered() && vk_dlaa_needs_restart(); }
@@ -990,43 +1005,48 @@ static void row_upscaling(void) {
// FSR 4 that failed in a row stays listed (it runs on this device) while FSR 3.1 serves: the row shows FSR 3.1, and
// choosing FSR 4 again tries it anew
if (e.kind == FSR4) vk_ffx4_retry();
// the Anti-aliasing row follows: DLSS and FSR 3.1 are its TAA, and leaving them leaves TAA for the game's SMAA
if (e.kind >= DLSS) opt_apply("NX2NAVI_AA", "taa");
else if (!strcmp(cfg_value("NX2NAVI_AA"), "taa")) opt_apply("NX2NAVI_AA", "game");
// The Anti-aliasing row keeps its choice, which runs along with DLSS's or FSR's TAA (vk_aa.c vk_aa_mode); its TAA
// went with the temporal mode, so leaving that leaves the game's SMAA
if (e.kind < DLSS && !strcmp(cfg_value("NX2NAVI_AA"), "taa")) opt_apply("NX2NAVI_AA", "game");
}
// Anti-aliasing (vk_aa.c NX2NAVI_AA): the game's own SMAA (the default), off, FXAA or SMAA in its place, or TAA, which is
// DLSS or FSR 3.1 at the scene's size, the Upscaling row's temporal modes. TAA is listed where one of them runs: NVIDIA
// DLAA where DLSS is offered, else FSR 3.1 Native AA where it loads. While a temporal mode is set (dlaa), the row shows
// TAA, noted as the Upscaling row's when that mode also scales. Choosing TAA sets the upscaler to the native mode;
// choosing another value turns the temporal upscaler off, with frame generation, which needs it, as the Upscaling row
// does for bilinear and FSR 1, and the picture is then fitted to the window as that row had it.
// DLSS or FSR at the scene's size, the Upscaling row's temporal modes. Without a temporal mode set (dlaa), TAA is listed
// where one runs: NVIDIA DLAA where DLSS is offered and taa does not name FSR, else FSR 4 Native AA where it runs, else
// FSR 3.1 Native AA where it loads; choosing it sets that native mode, as the Upscaling row would. While a temporal mode
// is set its TAA always runs, and the row picks what runs with it: the game's SMAA, nothing, FXAA or SMAA, noted as joined
// by the Upscaling row's TAA. A choice then leaves the upscaler and frame generation as they are. taa itself, set before
// or in the ini, shows as the game's SMAA, which is what runs with the upscaler (or without one, where it cannot run).
static void row_aa(void) {
enum { GAME, OFF, FXAA, SMAA, TAA };
static const char *const values[] = {"game", "off", "fxaa", "smaa", "taa"};
const bool dlss = dlss_offered(), fsr = vk_ffx_available(), temporal = cfg_bool("NX2NAVI_DLAA");
const bool fsr_set = !strcmp(cfg_value("NX2NAVI_TAA"), "fsr3");
const bool dlss = dlss_offered(), fsr = vk_ffx_available(), fsr4 = fsr && vk_ffx4_available();
const bool temporal = cfg_bool("NX2NAVI_DLAA"), fsr_set = !strcmp(cfg_value("NX2NAVI_TAA"), "fsr3");
const char *names[5] = {menu_text(UI_MENU_AA_GAME), menu_text(UI_MENU_FRAMEGEN_OFF), menu_text(UI_MENU_AA_FXAA),
menu_text(UI_MENU_AA_SMAA), nullptr};
int n = 4;
if (dlss || fsr || temporal)
names[n++] = menu_text((temporal ? !fsr_set : dlss) ? UI_MENU_AA_TAA_DLSS : UI_MENU_AA_TAA_FSR);
enum { NONE, K_DLSS, K_FSR3, K_FSR4 };
const int kind = dlss && (!fsr_set || !fsr) ? K_DLSS : fsr4 ? K_FSR4 : fsr ? K_FSR3 : NONE;
static char taa[96];
if (!temporal && kind) {
if (kind == K_FSR4) snprintf(taa, sizeof taa, menu_text(UI_MENU_AA_TAA_FSR4), fsr4_label());
else snprintf(taa, sizeof taa, "%s", menu_text(kind == K_DLSS ? UI_MENU_AA_TAA_DLSS : UI_MENU_AA_TAA_FSR));
names[n++] = taa;
}
int cur = GAME;
if (temporal) cur = TAA;
else
for (int i = 0; i < 4; i++)
if (!strcmp(cfg_value("NX2NAVI_AA"), values[i])) cur = i;
const char *note = temporal && strcmp(cfg_value("NX2NAVI_DLSS"), "dlaa") ? menu_text(UI_MENU_AA_UPSCALER) : nullptr;
for (int i = 0; i < 4; i++)
if (!strcmp(cfg_value("NX2NAVI_AA"), values[i])) cur = i;
// FSR 3.1 set where it cannot load runs nothing (the Upscaling row says so): no TAA joins the choice then
const char *note = temporal && (!fsr_set || fsr) ? menu_text(UI_MENU_AA_WITH_TAA) : nullptr;
int nv = opt_choice_index("NX2NAVI_AA", UI_MENU_AA, names, n, cur, GAME, UI_MENU_AA_DESC, note);
if (nv < 0 || nv >= n || nv == cur) return;
if (nv == TAA) {
if (nv == TAA) { // listed only without a temporal mode: the native one of that upscaler, as row_upscaling sets it
opt_apply("NX2NAVI_UPSCALER", "bilinear");
opt_apply("NX2NAVI_DLAA", "1");
opt_apply("NX2NAVI_DLSS", "dlaa");
opt_apply("NX2NAVI_TAA", dlss ? "dlss" : "fsr3");
if (!dlss) opt_apply("NX2NAVI_FSR4", "0");
} else if (temporal) {
opt_apply("NX2NAVI_DLAA", "0");
opt_apply("NX2NAVI_FRAMEGEN", "off");
opt_apply("NX2NAVI_TAA", kind == K_DLSS ? "dlss" : "fsr3");
if (kind != K_DLSS) opt_apply("NX2NAVI_FSR4", kind == K_FSR4 ? "1" : "0");
if (kind == K_FSR4) vk_ffx4_retry();
}
opt_apply("NX2NAVI_AA", values[nv]);
}
@@ -1886,27 +1906,28 @@ static void perf_picture(const MenuTarget *t, PerfPanel *p) {
snprintf(v[1], sizeof v[1], menu_text(UI_MENU_OV_FMT_SIZE), (unsigned)t->image_w, (unsigned)t->image_h);
snprintf(v[2], sizeof v[2], menu_text(UI_MENU_OV_FMT_SCENE), scene[0], scene[1], scene[0] * 100.0 / out[0]);
upscaling_name(v[3], sizeof v[3]);
aa_name(v[4], sizeof v[4]);
double hz = frame_step_limit_hz();
snprintf(v[4], sizeof v[4], "%s", menu_text(UI_MENU_OV_NONE));
if (hz > 0) snprintf(v[4], sizeof v[4], menu_text(UI_MENU_OV_FPS), hz);
snprintf(v[5], sizeof v[5], "%s", menu_text(strcmp(cfg_value("NX2NAVI_VK_PRESENT"), "immediate") ? UI_MENU_ON : UI_MENU_OFF));
v[6][0] = v[7][0] = 0;
snprintf(v[5], sizeof v[5], "%s", menu_text(UI_MENU_OV_NONE));
if (hz > 0) snprintf(v[5], sizeof v[5], menu_text(UI_MENU_OV_FPS), hz);
snprintf(v[6], sizeof v[6], "%s", menu_text(strcmp(cfg_value("NX2NAVI_VK_PRESENT"), "immediate") ? UI_MENU_ON : UI_MENU_OFF));
v[7][0] = v[8][0] = 0;
if (wide_available()) {
const char *a = cfg_value("NX2NAVI_GAME_ASPECT");
snprintf(v[6], sizeof v[6], "%s", menu_text(!strcmp(a, "window") ? UI_MENU_GAME_ASPECT_WINDOW : !strcmp(a, "21:9") ? UI_MENU_GAME_ASPECT_21_9
snprintf(v[7], sizeof v[7], "%s", menu_text(!strcmp(a, "window") ? UI_MENU_GAME_ASPECT_WINDOW : !strcmp(a, "21:9") ? UI_MENU_GAME_ASPECT_21_9
: !strcmp(a, "32:9") ? UI_MENU_GAME_ASPECT_32_9 : UI_MENU_GAME_ASPECT_16_9));
const char *r = cfg_value("NX2NAVI_GAME_RES");
if (!strcmp(r, "window")) snprintf(v[7], sizeof v[7], "%s", menu_text(UI_MENU_GAME_RES_NATIVE));
else snprintf(v[7], sizeof v[7], "%sp", r);
if (!strcmp(r, "window")) snprintf(v[8], sizeof v[8], "%s", menu_text(UI_MENU_GAME_RES_NATIVE));
else snprintf(v[8], sizeof v[8], "%sp", r);
}
const char *hdr = cfg_value("NX2NAVI_HDR");
snprintf(v[8], sizeof v[8], "%s", menu_text(!strcmp(hdr, "native") ? UI_MENU_HDR_NATIVE : cfg_bool("NX2NAVI_HDR") ? UI_MENU_HDR_TONEMAPPED : UI_MENU_FRAMEGEN_OFF));
snprintf(v[9], sizeof v[9], "%s", menu_text(!strcmp(hdr, "native") ? UI_MENU_HDR_NATIVE : cfg_bool("NX2NAVI_HDR") ? UI_MENU_HDR_TONEMAPPED : UI_MENU_FRAMEGEN_OFF));
const char *fg = cfg_value("NX2NAVI_FRAMEGEN");
const bool fsr_fg = !strcmp(fg, "fsr3") && vk_ffx_framegen_available(); // set but not loadable: off
snprintf(v[9], sizeof v[9], "%s", fsr_fg ? (vk_fg4_active() ? fg4_label() : "AMD FSR 3.1")
snprintf(v[10], sizeof v[10], "%s", fsr_fg ? (vk_fg4_active() ? fg4_label() : "AMD FSR 3.1")
: !strcmp(fg, "dlss") ? "NVIDIA DLSS" : menu_text(UI_MENU_FRAMEGEN_OFF));
if (!strcmp(fg, "dlss") && vk_dlssg_active()) // its multiplier as set, clamped to what this GPU allows
snprintf(v[9], sizeof v[9], "NVIDIA DLSS %dx",
snprintf(v[10], sizeof v[10], "NVIDIA DLSS %dx",
vk_dlssg_multiplier_of(cfg_value("NX2NAVI_FRAMEGEN_MULTIPLIER"), vk_dlssg_multiplier_max(nullptr), nullptr));
// The 3D scene's size is known only where resolution.c sets it (the builds with its patch sets); Ocarina sizes its
// own scene dynamically and res_sizes would report a fixed 1600x900, so the line is left out

View File

@@ -165,14 +165,15 @@ void waits(const PerfStats &s) {
}
void picture(const PerfPanel *p) {
static const UiTextId labels[10] = {UI_MENU_OV_WINDOW, UI_MENU_OV_OUTPUT, UI_MENU_OV_SCENE, UI_MENU_UPSCALING, UI_MENU_OV_LIMIT,
UI_MENU_PRESENT_VSYNC, UI_MENU_GAME_ASPECT, UI_MENU_GAME_RES, UI_MENU_HDR, UI_MENU_FRAMEGEN};
static const UiTextId labels[11] = {UI_MENU_OV_WINDOW, UI_MENU_OV_OUTPUT, UI_MENU_OV_SCENE, UI_MENU_UPSCALING, UI_MENU_AA,
UI_MENU_OV_LIMIT, UI_MENU_PRESENT_VSYNC, UI_MENU_GAME_ASPECT, UI_MENU_GAME_RES, UI_MENU_HDR,
UI_MENU_FRAMEGEN};
if (!ImGui::BeginTable("##perfp", 2, ImGuiTableFlags_SizingFixedFit)) return;
float vw = 0;
for (const auto &v : p->picture) vw = fmaxf(vw, ImGui::CalcTextSize(v).x);
ImGui::TableSetupColumn("##p0", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##p1", ImGuiTableColumnFlags_WidthFixed, vw);
for (int i = 0; i < 10; i++) {
for (int i = 0; i < 11; i++) {
if ((i == 2 && !p->scene_known) || !p->picture[i][0]) continue;
label(labels[i]);
ImGui::TableNextColumn();

View File

@@ -10,9 +10,9 @@ extern "C" {
typedef struct {
PerfStats s; // perfmon_snapshot
const char *version; // "NX2navi <version>, game <update>"
// window, game image, scene, then the settings as the menu names them: upscaling, frame limit, VSync, widescreen,
// resolution, HDR, frame generation. An empty string leaves its line out.
char picture[10][64];
// window, game image, scene, then the settings as the menu names them: upscaling, anti-aliasing, frame limit, VSync,
// widescreen, resolution, HDR, frame generation. An empty string leaves its line out.
char picture[11][64];
bool scene_known; // the scene line is shown (resolution.c sets the scene's size)
float fg_fps; // frames the display gets with frame generation, 0 without it
bool under_menu; // the menu is open: the panel goes under its window

View File

@@ -154,14 +154,16 @@ static const char *const text_en[UI_TEXT_COUNT] = {
[UI_MENU_AA] = "Anti-aliasing",
[UI_MENU_AA_DESC] = "How the edges of the 3D picture are smoothed. Game SMAA is the game's own, as on the console. Off "
"leaves the edges as drawn. FXAA is quick and a little soft. SMAA finds more of the edges than the "
"game's and keeps detail sharp. TAA is DLSS or FSR 3.1 at full size: the steadiest edges in motion; "
"it sets the upscaler. Takes effect at once.",
"game's and keeps detail sharp. TAA is DLSS or FSR at full size: the steadiest edges in motion; it "
"sets the upscaler. With DLSS or FSR set under Upscaling their TAA always runs, and the "
"choice here runs along with it. Takes effect at once.",
[UI_MENU_AA_GAME] = "Game SMAA",
[UI_MENU_AA_FXAA] = "FXAA",
[UI_MENU_AA_SMAA] = "SMAA (Ultra)",
[UI_MENU_AA_TAA_DLSS] = "TAA (NVIDIA DLAA)",
[UI_MENU_AA_TAA_FSR] = "TAA (AMD FSR 3.1)",
[UI_MENU_AA_UPSCALER] = "set by Upscaling",
[UI_MENU_AA_TAA_FSR4] = "TAA (%s)", // FSR 4's name as the Upscaling row gives it ("AMD FSR 4.1")
[UI_MENU_AA_WITH_TAA] = "plus TAA from Upscaling",
[UI_MENU_FPS_LIMIT] = "Frame rate limit",
[UI_MENU_FPS_LIMIT_DESC] = "The highest frame rate the game draws at. Frame generation adds its frames on top.",
@@ -844,14 +846,16 @@ static const char *const text_ru[UI_TEXT_COUNT] = {
[UI_MENU_AA] = "Сглаживание",
[UI_MENU_AA_DESC] = "Как сглаживаются края 3D-картинки. SMAA игры — собственное, как на консоли. «Выкл.» оставляет края "
"как есть. FXAA быстрое и слегка мягкое. SMAA находит больше краёв, чем игровое, и сохраняет "
"чёткость. TAA — это DLSS или FSR 3.1 в полном размере: самые устойчивые края в движении; задаёт "
"масштабирование. Действует сразу.",
"чёткость. TAA — это DLSS или FSR в полном размере: самые устойчивые края в движении; задаёт "
"масштабирование. Когда в Upscaling выбран DLSS или FSR, их TAA работает всегда, а "
"выбранное здесь — вместе с ним. Действует сразу.",
[UI_MENU_AA_GAME] = "SMAA игры",
[UI_MENU_AA_FXAA] = "FXAA",
[UI_MENU_AA_SMAA] = "SMAA (Ultra)",
[UI_MENU_AA_TAA_DLSS] = "TAA (NVIDIA DLAA)",
[UI_MENU_AA_TAA_FSR] = "TAA (AMD FSR 3.1)",
[UI_MENU_AA_UPSCALER] = "задано масштабированием",
[UI_MENU_AA_TAA_FSR4] = "TAA (%s)",
[UI_MENU_AA_WITH_TAA] = "плюс TAA из Upscaling",
[UI_MENU_FPS_LIMIT] = "Ограничение частоты кадров",
[UI_MENU_FPS_LIMIT_DESC] = "Максимальная частота кадров, которые рисует игра. Генерация кадров добавляет свои сверх неё.",
@@ -1836,14 +1840,16 @@ static const char *const text_pt_br[UI_TEXT_COUNT] = {
[UI_MENU_AA] = "Antisserrilhado",
[UI_MENU_AA_DESC] = "Como as bordas da imagem 3D são suavizadas. SMAA do jogo é o próprio, como no console. Desligado "
"deixa as bordas como desenhadas. FXAA é rápido e um pouco suave. SMAA encontra mais bordas que o do "
"jogo e mantém os detalhes nítidos. TAA é o DLSS ou o FSR 3.1 em tamanho cheio: as bordas mais "
"estáveis em movimento; define o escalonamento. Vale na hora.",
"jogo e mantém os detalhes nítidos. TAA é o DLSS ou o FSR em tamanho cheio: as bordas mais "
"estáveis em movimento; define o escalonamento. Com DLSS ou FSR em Upscaling, o TAA deles "
"sempre roda, e a escolha daqui roda junto. Vale na hora.",
[UI_MENU_AA_GAME] = "SMAA do jogo",
[UI_MENU_AA_FXAA] = "FXAA",
[UI_MENU_AA_SMAA] = "SMAA (Ultra)",
[UI_MENU_AA_TAA_DLSS] = "TAA (NVIDIA DLAA)",
[UI_MENU_AA_TAA_FSR] = "TAA (AMD FSR 3.1)",
[UI_MENU_AA_UPSCALER] = "definido pelo escalonamento",
[UI_MENU_AA_TAA_FSR4] = "TAA (%s)",
[UI_MENU_AA_WITH_TAA] = "mais o TAA do Upscaling",
[UI_MENU_TAB_CHEATS] = "Cheats",
[UI_MENU_CHEATS_NONE] = "Nenhum cheat para esta versão do jogo. Os cheats de um mod são um arquivo de cheats do "
"Atmosphere na pasta cheats dele, com o nome da build do jogo: mods\\<mod>\\cheats\\%s. "
@@ -2614,13 +2620,15 @@ static const char *const text_zh_hans[UI_TEXT_COUNT] = {
[UI_MENU_FXAA_DESC] = "游戏自身的 FXAA 边缘平滑。会让细节略微模糊;开启 DLAA 时不需要。",
[UI_MENU_AA] = "抗锯齿",
[UI_MENU_AA_DESC] = "3D 画面边缘的平滑方式。游戏 SMAA 是游戏自带的,与主机相同。关闭则保留原始边缘。FXAA 快速,略显柔和。SMAA 比游戏自带的找到更多边缘,并保持细节清晰。TAA 即全尺寸的 DLSS 或 "
"FSR 3.1:运动中边缘最稳定;它会设置放大方式。立即生效。",
"FSR:运动中边缘最稳定;它会设置放大方式。在 Upscaling 中选择 DLSS 或 FSR 时,它们的 TAA 始终运行,"
"此处的选择与其一同运行。立即生效。",
[UI_MENU_AA_GAME] = "游戏 SMAA",
[UI_MENU_AA_FXAA] = "FXAA",
[UI_MENU_AA_SMAA] = "SMAA(极高)",
[UI_MENU_AA_TAA_DLSS] = "TAA(NVIDIA DLAA)",
[UI_MENU_AA_TAA_FSR] = "TAA(AMD FSR 3.1)",
[UI_MENU_AA_UPSCALER] = "由放大设置决定",
[UI_MENU_AA_TAA_FSR4] = "TAA(%s)",
[UI_MENU_AA_WITH_TAA] = "另加 Upscaling 的 TAA",
[UI_MENU_TAB_CHEATS] = "金手指",
[UI_MENU_CHEATS_NONE] = "此游戏版本没有金手指。模组的金手指是它的 cheats 文件夹中以游戏构建命名的 Atmosphere "
"金手指文件:mods\\<模组>\\cheats\\%s。重启游戏后才会读取。对于修改游戏代码的金手指,"

View File

@@ -62,7 +62,7 @@ typedef enum {
UI_MENU_DLSS_PRESET_DEFAULT, UI_MENU_DLSS_PRESET_K, UI_MENU_DLSS_PRESET_J, UI_MENU_DLSS_CHARS, UI_MENU_DLSS_CHARS_DESC,
UI_MENU_DLSS_CHARS_OFF, UI_MENU_DLSS_CHARS_LIGHT, UI_MENU_DLSS_CHARS_MEDIUM, UI_MENU_DLSS_CHARS_FULL, UI_MENU_FXAA, UI_MENU_FXAA_DESC,
UI_MENU_AA, UI_MENU_AA_DESC, UI_MENU_AA_GAME, UI_MENU_AA_FXAA, UI_MENU_AA_SMAA, UI_MENU_AA_TAA_DLSS, UI_MENU_AA_TAA_FSR,
UI_MENU_AA_UPSCALER,
UI_MENU_AA_TAA_FSR4, UI_MENU_AA_WITH_TAA,
// Game
UI_MENU_FPS_LIMIT, UI_MENU_FPS_LIMIT_DESC, UI_MENU_FPS_30, UI_MENU_FPS_40, UI_MENU_FPS_45, UI_MENU_FPS_60, UI_MENU_FPS_90,

View File

@@ -10,9 +10,11 @@
// replace the composition (vk_exec_draw.c aa_dispatch) with one of the passes here, which read the same composite and
// write the same words: off stores it as it is, fxaa smooths it first (shaders/aa_post.comp), smaa runs SMAA at its
// Ultra preset (shaders/smaa_*.comp, the reference implementation in shaders/smaa.glsl with the area and search
// textures of third_party/smaa). taa is DLSS or FSR 3.1 at the scene's own size: the menu sets the upscaler for it
// (ui/menu.cpp row_aa). While DLSS or FSR 3.1 anti-aliases the scene (dlaa = 1 and it runs), the game's SMAA stays as it
// is whatever aa says: they take the picture after it, and their inputs are tuned with it.
// textures of third_party/smaa). taa is DLSS or FSR at the scene's own size: the menu sets the upscaler for it
// (ui/menu.cpp row_aa), and the game's SMAA runs with it. While DLSS or FSR anti-aliases or scales the scene (dlaa = 1),
// game, off, fxaa and smaa still choose the pass above: in their native modes the upscalers run before the bloom (vk_dlaa.c,
// "where DLAA runs") and the pass smooths their picture after it, in the scaling modes the pass runs on the scene first
// and the upscaler scales its result. off then leaves the upscaler's TAA alone on the edges.
//
// The game's passes are known by a hash of their guest code (vk_aa_role), which does not change with the translator or
// its settings. Everything here runs on the replay thread.
@@ -61,13 +63,13 @@ int vk_aa_role(uint64_t guest_hash) {
static const char *const NAMES[] = {"game", "off", "fxaa", "smaa"};
// DLSS or FSR 3.1 anti-aliases this frame's scene: dlaa = 1 and one of them runs (vk_dlaa.c)
// DLSS or FSR anti-aliases this frame's scene: dlaa = 1 and one of them runs (vk_dlaa.c)
static int temporal(void) { return cfg_bool("NX2NAVI_DLAA") && (vk_dlaa_available() || vk_dlaa_fsr3()); }
static struct {
uint64_t frame_read;
int mode; // this frame's (vk_aa_mode)
int said; // the last refusal logged: 1 + the mode refused, 0 none
int said; // taa was last logged as waiting for DLSS or FSR
int composed; // the last composition seen was replaced (vk_aa_composed): the passes before it may go
uint64_t frames_on, composes; // frames with a replacement asked for, compositions replaced
int none_told;
@@ -81,14 +83,13 @@ int vk_aa_mode(void) {
int want = VK_AA_GAME;
for (int i = 1; i < 4; i++)
if (!strcmp(v, NAMES[i])) want = i;
int tmp = want != VK_AA_GAME && temporal();
int said = tmp ? 1 + want : !strcmp(v, "taa") && !temporal() ? 1 + 4 : 0;
// taa is the game's SMAA with DLSS's or FSR's TAA; without them at work, the game's SMAA alone
int said = !strcmp(v, "taa") && !temporal();
if (said != A.said) {
A.said = said;
if (said == 5) rt_log("aa: taa needs DLSS or FSR 3.1 at work (dlaa = 1): the game's SMAA stays");
else if (said) rt_log("aa: %s waits while DLSS or FSR 3.1 anti-aliases the scene: the game's SMAA stays", NAMES[want]);
if (said) rt_log("aa: taa needs DLSS or FSR at work (dlaa = 1): the game's SMAA stays");
}
A.mode = tmp ? VK_AA_GAME : want;
A.mode = want;
if (A.mode != VK_AA_GAME && !A.none_told && ++A.frames_on == 3600 && !A.composes) {
A.none_told = 1; // a game version or a frame without the passes this file knows: nothing is replaced
rt_log("aa: aa = %s found none of the game's SMAA passes in %llu frames: the picture stays the game's",