diff --git a/docs/architecture.md b/docs/architecture.md index d9f0d735..539bd2c7 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -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 diff --git a/docs/releases/v0.9.1.md b/docs/releases/v0.9.1.md new file mode 100644 index 00000000..4af20399 --- /dev/null +++ b/docs/releases/v0.9.1.md @@ -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. diff --git a/nx2navi.ini.example b/nx2navi.ini.example index 931959ff..b9b7ce56 100644 --- a/nx2navi.ini.example +++ b/nx2navi.ini.example @@ -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). diff --git a/runtime/ui/menu.cpp b/runtime/ui/menu.cpp index beb9ccc3..e318b28e 100644 --- a/runtime/ui/menu.cpp +++ b/runtime/ui/menu.cpp @@ -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 diff --git a/runtime/ui/perf_panel.cpp b/runtime/ui/perf_panel.cpp index 5f959a16..32d72b12 100644 --- a/runtime/ui/perf_panel.cpp +++ b/runtime/ui/perf_panel.cpp @@ -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(); diff --git a/runtime/ui/perf_panel.h b/runtime/ui/perf_panel.h index a3142a3f..b03d3cd5 100644 --- a/runtime/ui/perf_panel.h +++ b/runtime/ui/perf_panel.h @@ -10,9 +10,9 @@ extern "C" { typedef struct { PerfStats s; // perfmon_snapshot const char *version; // "NX2navi , game " - // 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 diff --git a/runtime/ui_text.c b/runtime/ui_text.c index 61bb391d..9f7402bc 100644 --- a/runtime/ui_text.c +++ b/runtime/ui_text.c @@ -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\\\\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。重启游戏后才会读取。对于修改游戏代码的金手指," diff --git a/runtime/ui_text.h b/runtime/ui_text.h index 5215dc93..9d098b1f 100644 --- a/runtime/ui_text.h +++ b/runtime/ui_text.h @@ -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, diff --git a/runtime/vk_aa.c b/runtime/vk_aa.c index d1aa5bd7..1798f013 100644 --- a/runtime/vk_aa.c +++ b/runtime/vk_aa.c @@ -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",