Put the low-end GPU mode in the settings menu's Game tab, marked experimental.

The row sets low_end_gpu, read at start, and says what the mode turns on and that it was measured on one card; its text is there in the menu's four languages. The key is decided again once the settings file is read.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
chrg6
2026-11-12 13:06:02 -05:00
parent 2324a74602
commit d2fbaba1c3
6 changed files with 35 additions and 12 deletions

View File

@@ -16,8 +16,9 @@ for the launcher; a GPU with Vulkan 1.3 and `VK_EXT_external_memory_host` (curre
## New
- **An option for older graphics cards: `low_end_gpu = 1` in nx2navi.ini.** It turns on a set of changes written by
Tobim6 and measured on a Radeon RX 580. They are off by default, because they were not run by us on other cards:
- **An experimental mode for older graphics cards:** *Low-end GPU mode (experimental)* in the settings menu's Game
tab, or `low_end_gpu = 1` in nx2navi.ini. It turns on a set of changes written by Tobim6 and measured on a Radeon
RX 580. They are off by default, because they were not run by us on other cards:
- Grass, moss and other foliage on cards without mesh shaders (AMD before RDNA 2, such as the RX 400 and 500 series
and Vega; NVIDIA before the GTX 16 and RTX 20 series): the game's mesh shaders run as compute shaders and what
they make is drawn as ordinary triangles.

View File

@@ -288,15 +288,15 @@
# which game memory gets no copy in video memory (memory = mirror), which costs far more frame time than a texture
# uploaded again. 0: textures never give way for video memory.
# tex_vram_pressure = 80
# Older graphics cards, and ones short of video memory: 1 turns on the settings written for them and measured on a
# Radeon RX 580, for every key below that this file does not set itself. Mesh shaders run as compute where the card
# has none (mesh_emulation), video memory stays within what the driver reports free (vram_heap_limit = auto,
# vram_reserve_mb = 512), large texture upload batches go to the GPU early (upload_batch_mb = 256), game memory is
# copied for the GPU while a frame is recorded and the game waits less for the GPU (mirror_stage = 1,
# submit_finish_gpu = 0), frames are prepared on a thread of their own (replay_async = 1, which can show a dark or
# flickering frame now and then), pools the game refills every frame stay in system memory (mirror_hot = 25), and a
# texture read after another image was drawn over its memory gets memory of its own (tex_clobber = 1). 0, the
# default: each of these stays as it was in 0.9.1. Read at start.
# Low-end GPU mode (experimental; also in the settings menu's Game tab). For older graphics cards, and ones short of
# video memory: 1 turns on the settings written for them and measured on a Radeon RX 580, for every key below that
# this file does not set itself. Mesh shaders run as compute where the card has none (mesh_emulation), video memory
# stays within what the driver reports free (vram_heap_limit = auto, vram_reserve_mb = 512), large texture upload
# batches go to the GPU early (upload_batch_mb = 256), game memory is copied for the GPU while a frame is recorded and
# the game waits less for the GPU (mirror_stage = 1, submit_finish_gpu = 0), frames are prepared on a thread of their
# own (replay_async = 1, which can show a dark or flickering frame now and then), pools the game refills every frame
# stay in system memory (mirror_hot = 25), and a texture read after another image was drawn over its memory gets
# memory of its own (tex_clobber = 1). 0, the default: each of these stays as it was in 0.9.1. Read at start.
# low_end_gpu = 0
# Textures the game released that are kept as they are (1 to 16384); past this count only those that lose nothing
# when dropped go. Default: one per 2 MB of the video memory budget, 2048 to 8192. Read at start.

View File

@@ -1157,6 +1157,7 @@ int cfg_ini_now(const char *key, char *out, size_t cap) { return find_ini() ? cf
void cfg_init(void) {
load_ini();
__atomic_store_n(&lowend, -1, __ATOMIC_RELEASE); // asked before the file was read: decided again (lowend_of)
if (profile_of())
rt_log("cfg: device profile Steam Deck: defaults for the keys nx2navi.ini does not set (NX2NAVI_DEVICE_PROFILE=desktop "
"turns it off)");

View File

@@ -1404,6 +1404,8 @@ static void tab_game(float scale) {
row_game_lang();
static const UiTextId mode[] = {UI_MENU_MODE_DOCKED, UI_MENU_MODE_HANDHELD};
opt_choice("NX2NAVI_OPERATION_MODE", UI_MENU_OPERATION_MODE, mode, 2, UI_MENU_OPERATION_MODE_DESC);
// cfg.c LOWEND: the defaults for older graphics cards, read at start
opt_toggle("NX2NAVI_LOW_END_GPU", UI_MENU_LOW_END_GPU, UI_MENU_LOW_END_GPU_DESC);
opt_toggle("NX2NAVI_ASSUME_FOCUS", UI_MENU_ASSUME_FOCUS, UI_MENU_ASSUME_FOCUS_DESC);
// discord_rpc.c reads the setting on its own thread and connects or clears the status within half a second
opt_toggle("NX2NAVI_DISCORD_RPC", UI_MENU_DISCORD_RPC, UI_MENU_DISCORD_RPC_DESC);

View File

@@ -465,6 +465,11 @@ static const char *const text_en[UI_TEXT_COUNT] = {
[UI_MENU_AMIIBO_STATUS] = "Status: %s",
[UI_MENU_MENU_LANG] = "Menu language", [UI_MENU_MENU_LANG_DESC] = "Language of this menu and the overlay.",
[UI_MENU_MENU_LANG_AUTO] = "Automatic (from Windows)",
[UI_MENU_LOW_END_GPU] = "Low-end GPU mode (experimental)",
[UI_MENU_LOW_END_GPU_DESC] = "For older graphics cards and cards short of video memory. Runs the game's mesh shaders as compute shaders "
"where the card has none, keeps video memory within what the driver reports free, waits less for the GPU and "
"prepares frames on a thread of their own. Measured on a Radeon RX 580 only: it can show a dark or flickering "
"frame now and then, so leave it off on a newer card.",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "Shows \"Playing NX2navi\" with the play time in your Discord status while the "
"game runs. discord_app_id and discord_image in nx2navi.ini choose the application.",
@@ -1154,6 +1159,11 @@ static const char *const text_ru[UI_TEXT_COUNT] = {
[UI_MENU_AMIIBO_STATUS] = "Состояние: %s",
[UI_MENU_MENU_LANG] = "Язык меню", [UI_MENU_MENU_LANG_DESC] = "Язык этого меню и индикатора.",
[UI_MENU_MENU_LANG_AUTO] = "Автоматически (из Windows)",
[UI_MENU_LOW_END_GPU] = "Режим для слабых видеокарт (экспериментальный)",
[UI_MENU_LOW_END_GPU_DESC] = "Для старых видеокарт и карт с малым объёмом видеопамяти. Меш-шейдеры игры выполняются как вычислительные там, "
"где карта их не поддерживает, видеопамять удерживается в пределах свободного объёма по данным драйвера, игра "
"меньше ждёт видеокарту, а кадры готовятся в отдельном потоке. Проверено только на Radeon RX 580: изредка "
"возможен тёмный или мерцающий кадр, поэтому на новой карте оставьте выключенным.",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "Пока игра запущена, показывает «Играю в NX2navi» со временем игры в статусе "
"Discord. Приложение выбирают discord_app_id и discord_image в nx2navi.ini.",
@@ -1685,6 +1695,11 @@ static const char *const text_pt_br[UI_TEXT_COUNT] = {
[UI_MENU_AMIIBO_STATUS] = "Estado: %s",
[UI_MENU_MENU_LANG] = "Idioma do menu", [UI_MENU_MENU_LANG_DESC] = "Idioma deste menu e do indicador.",
[UI_MENU_MENU_LANG_AUTO] = "Automático (do Windows)",
[UI_MENU_LOW_END_GPU] = "Modo para GPUs fracas (experimental)",
[UI_MENU_LOW_END_GPU_DESC] = "Para placas de vídeo antigas ou com pouca memória de vídeo. Executa os mesh shaders do jogo como compute "
"shaders onde a placa não os tem, mantém a memória de vídeo dentro do que o driver informa como livre, espera "
"menos pela GPU e prepara os quadros numa thread própria. Medido apenas numa Radeon RX 580: pode mostrar um "
"quadro escuro ou piscando de vez em quando, então deixe desligado numa placa mais nova.",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "Mostra \"Jogando NX2navi\" com o tempo de jogo no seu status do Discord "
"enquanto o jogo roda. discord_app_id e discord_image no nx2navi.ini escolhem a "
@@ -2459,6 +2474,10 @@ static const char *const text_zh_hans[UI_TEXT_COUNT] = {
[UI_MENU_MENU_LANG] = "菜单语言",
[UI_MENU_MENU_LANG_DESC] = "本菜单和性能浮层的语言。",
[UI_MENU_MENU_LANG_AUTO] = "自动(跟随 Windows)",
[UI_MENU_LOW_END_GPU] = "低端显卡模式(实验性)",
[UI_MENU_LOW_END_GPU_DESC] = "适用于较旧的显卡和显存不足的显卡。在显卡不支持网格着色器时以计算着色器运行游戏的网格着色器,"
"将显存占用控制在驱动报告的可用范围内,减少等待 GPU 的时间,并在独立线程上准备帧。"
"仅在 Radeon RX 580 上测试过:偶尔可能出现变暗或闪烁的画面,较新的显卡请保持关闭。",
[UI_MENU_DISCORD_RPC] = "Discord Rich Presence",
[UI_MENU_DISCORD_RPC_DESC] = "游戏运行时在 Discord 状态中显示“正在玩 NX2navi”及游戏时长。nx2navi.ini 中的 "
"discord_app_id 和 discord_image 选择应用。",

View File

@@ -164,7 +164,7 @@ typedef enum {
// Menu tab
UI_MENU_MENU_LANG, UI_MENU_MENU_LANG_DESC, UI_MENU_MENU_LANG_AUTO,
UI_MENU_DISCORD_RPC, UI_MENU_DISCORD_RPC_DESC,
UI_MENU_DISCORD_RPC, UI_MENU_DISCORD_RPC_DESC, UI_MENU_LOW_END_GPU, UI_MENU_LOW_END_GPU_DESC,
// Language names, each in its own language and the same in every row (game language and menu language lists)
UI_MENU_LANGNAME_EN, UI_MENU_LANGNAME_JA, UI_MENU_LANGNAME_FR, UI_MENU_LANGNAME_DE, UI_MENU_LANGNAME_IT,