Offer the low-end GPU mode only on the cards it was written for.

On a card with mesh shaders and 8 GiB of video memory or more the Game tab's switch cannot turn the mode on; it stays usable while the mode is on, to turn it off again. A player with every setting at its highest had it on on a GeForce RTX 5090, where the mode moved the sun shadow map and the scene depth to memory of their own and the ground's shadow became a dark patch with straight edges that turned with the camera.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
chrg6
2026-11-12 14:28:36 -05:00
parent 26f3dc47ec
commit 3123d40017
4 changed files with 19 additions and 1 deletions

View File

@@ -84,6 +84,7 @@ int vk_fg4_active(void); // ... its swapchain is in place
const char *vk_fg4_name(void); // ... the version the library runs here ("3.1.6", "4.0.2")
int vk_texture_detail_auto(void); // vk_texture.c: the texture detail auto picks on this card, 0 full to 2 low
int vk_mesh_shader_native(void); // vk_device.c: the GPU has mesh shaders (the mesh emulation does nothing)
int vk_low_end_card(void); // vk_device.c: no mesh shaders, or under 8 GiB of video memory
double frame_step_limit_hz(void);
int frame_limit_adjustable(void);
int rtss_limit_state(void);
@@ -1423,6 +1424,10 @@ static void tab_game(float scale) {
}
// Last, as its own settings follow it while it is on (rows_low_end). cfg.c LOWEND: the defaults for older graphics
// cards, read at start.
// Offered on the cards it was written for (vk_low_end_card). On any other the row cannot turn the mode on; while
// the mode is on there (set earlier, or in nx2navi.ini) the row stays usable, to turn it off again.
if (!cfg_bool("NX2NAVI_LOW_END_GPU") && !cfg_low_end_active() && !vk_low_end_card())
opt_disable_next(UI_MENU_LOWEND_NOT_FOR_CARD);
opt_toggle("NX2NAVI_LOW_END_GPU", UI_MENU_LOW_END_GPU, UI_MENU_LOW_END_GPU_DESC);
// the mode's settings are read only while it is on (cfg.c LOWEND_ONLY), so their rows wait for the restart too
if (cfg_low_end_active()) rows_low_end();

View File

@@ -91,6 +91,8 @@ static const char *const text_en[UI_TEXT_COUNT] = {
[UI_MENU_TEX_DETAIL_FULL] = "Full", [UI_MENU_TEX_DETAIL_REDUCED] = "Reduced", [UI_MENU_TEX_DETAIL_LOW] = "Low",
[UI_MENU_LOWEND_INTRO] = "The settings of the low-end GPU mode. Each can be changed here; most take effect after a restart.",
[UI_MENU_LOWEND_RESTART] = "The mode turns on after a restart. Its settings are listed here then.",
[UI_MENU_LOWEND_NOT_FOR_CARD] = "Not for this graphics card: it has mesh shaders and 8 GB of video memory or more. "
"The mode is for older cards and can break shadows on this one.",
[UI_MENU_LOWEND_MEMORY] = "Video memory and textures",
[UI_MENU_LOWEND_RENDER] = "Rendering",
[UI_MENU_LOWEND_BUILD] = "Build",

View File

@@ -333,7 +333,7 @@ typedef enum {
UI_MENU_FRAMEGEN_MULT_OLD_DLL, // nx2navi_dlssg.dll is older than multi frame generation
UI_MENU_FRAMEGEN_UNAVAILABLE, UI_MENU_FRAMEGEN_OFF_FILES,
// the settings of the low-end GPU mode (ui/menu.cpp rows_low_end), English only
UI_MENU_LOWEND_INTRO, UI_MENU_LOWEND_RESTART, UI_MENU_LOWEND_MEMORY, UI_MENU_LOWEND_RENDER, UI_MENU_LOWEND_BUILD,
UI_MENU_LOWEND_INTRO, UI_MENU_LOWEND_RESTART, UI_MENU_LOWEND_NOT_FOR_CARD, UI_MENU_LOWEND_MEMORY, UI_MENU_LOWEND_RENDER, UI_MENU_LOWEND_BUILD,
UI_MENU_LOWEND_DIAG,
UI_MENU_LOWEND_FREEZE, UI_MENU_LOWEND_FREEZE_DESC, UI_MENU_LOWEND_ZSTD, UI_MENU_LOWEND_ZSTD_DESC,
UI_MENU_LOWEND_FOLIAGE, UI_MENU_LOWEND_FOLIAGE_DESC, UI_MENU_LOWEND_FOLIAGE_FULL, UI_MENU_LOWEND_FOLIAGE_REDUCED,

View File

@@ -863,3 +863,14 @@ int probe_vkdevice(void) {
// The GPU has mesh shaders: the mesh emulation (NX2NAVI_MESH_EMULATION) does nothing there (the low-end GPU rows of the menu's Game tab).
int vk_mesh_shader_native(void) { return g_vk.has_mesh_shader; }
// The card the low-end GPU mode (cfg.c LOWEND) was written for: one without mesh shaders, or one whose driver reports
// a video memory budget under 8 GiB. The menu offers the mode only there (ui/menu.cpp tab_game): on a GeForce RTX 5090
// the mode's own-memory rule for overwritten textures moved the 1600x1600 sun shadow map and the scene depth to memory
// of their own, and the ground's shadow was a dark patch with straight edges that turned with the camera.
int vk_low_end_card(void) {
if (!g_vk.has_mesh_shader) return 1;
uint64_t used = 0, budget = 0;
int exact = 0;
return vk_mem_vram(&used, &budget, &exact) && budget && budget >> 20 < 8192;
}