diff --git a/nx2navi.ini.example b/nx2navi.ini.example index 15ed5851..9408b580 100644 --- a/nx2navi.ini.example +++ b/nx2navi.ini.example @@ -421,6 +421,9 @@ # is read and written by the GPU in system memory instead (0: every pool keeps its video memory copy). For GPUs and # buses short of bandwidth; on an RX 580 the pools the game refills every frame cost about 8 ms a frame in copies. # mirror_hot = 0 +# 2: the next Rebuild the Game compiles the game's code at -O2 instead of -O1 (faster game threads on a slower CPU, a +# build several times longer). Read by tools/make_game.py; the environment variable NX2NAVI_GUEST_OPT wins. +# guest_opt = 1 # GPUs without mesh shaders (VK_EXT_mesh_shader: AMD before RDNA 2, NVIDIA before Turing): 1 runs the game's mesh # and task shaders (grass and other foliage) as compute shaders and draws what they make; 0 skips those draws. The # arena for their vertices and triangles is mesh_emu_mb MiB of video memory, with mesh_emu_tasks task records (3 KiB diff --git a/runtime/cfg.c b/runtime/cfg.c index c0ea134d..e546128b 100644 --- a/runtime/cfg.c +++ b/runtime/cfg.c @@ -61,6 +61,7 @@ static const char *const known[] = { "ONE_PER_CORE", "OPERATION_MODE", "OUTPUT_RES", "PAD_LAYOUT", "PACE_HZ", "PASS_CRUMBS", "PATCH_OUTPUT", "PATCH_RES_FIXED", "PATCH_SCENE", "PATCH_WIDE_ASPECT", "PATCH_WIDE_HUD", "PATCH_WIDE_MOVIE", "PATCH_WIDE_OUT", "PATCH_FREECAM", "PATCH_WIDE_SCENE", "PCSS", "PCSS_K", "PERF_OVERLAY", "PERF_SLOW_MS", "PIPELINE_CACHE", "PIPELINE_CACHE_MAX_MB", "PIPELINE_CACHE_PLAY", "PIPELINE_CACHE_PLAY_MB", "PIPE_BINARIES", "PIPE_BINARIES_MAX_MB", "PIPE_FEEDBACK", "PIPE_MEMO", "PIPE_PREBUILD", "PIPE_SEED", "PIPE_SKIP", "PIPE_SYNC", "PIPE_WAIT", "POWER_FULL", "TEX_SAME", "TEX_FLAT3D", "TEX_KEEP_TAKEN", "TEX_STALE_KEPT", "PRESENT_HELD", "HELD_SYNC", "PREPARE_PIPELINES", "PREWARM_FULL", "PREWARM_WAIT_MS", "PREWARM_XLATE", "PROBE_MOVIE", "PROBE_MOVIE_SHOT", "PROFILE", "PROFILE_CHAINS", "PROFILE_DIR", "PROFILE_FRAMES", "PROFILE_REPLAY", "PROFILE_SLOW", "POOL_FAST", "POOL_GROUP", "POOL_GROUP_CHECK", "POOL_PRESNAP", + "SUBMIT_FINISH_GPU", "SVC_WAITS", "SNAP_WIDEN", "SUBMIT_FINISH_RESULTS", "SUBMIT_FINISH_KINDS", "FOLIAGE", "MIRROR_STAGE", "FLUSH_SKIP_CLEAN", "MIRROR_HOT", "MESH_EMULATION", "MESH_EMU_MB", "MESH_EMU_TASKS", "MESH_EMU_BATCH", "GUEST_OPT", "LOG_TEX_NEW", "DUMP_KEY", "VEC_INDEX_FIX", "PASS_TIMES", "PROFILE_MAIN", "PROFILE_RENDER", "PROMPTS", "PUSH_SKIP", "PUSH_STAGE", "RDOC", "RDOC_DIR", "RDOC_DLL", "REALTIME", "REC_END", "REEXEC", "REFLEX", "RENDER_SCALE", "REPLAY_ASYNC", "REPLAY_PIPE", "REPLAY_RUNS", "REPLAY_WORKERS", "RTSS", "RTSS_ENUM", "SCENE_SHARE", "PRESNAP_PLACE", @@ -73,6 +74,7 @@ static const char *const known[] = { "SET_AT", "SWKBD_TEST", "TAA", "DBG_TEST", "DEBUG_MENU", "MENU_TEST_DEBUG", "FSR4", "FSR4_FG", "FG4_VERSION", "FG4_SWAPCHAIN", "TEST_PAD", "TEST_PAD_AT", "TEST_PREPARE_SHADERS", "TEX_ALIAS", "DEPTH_INIT_INLINE", "DEPTH_ALIAS_LOG", "TEX_DISUSE", "TEX_DISUSE_EVICT", "TEX_GEN_UNDO", "TEX_MEMO", "TEX_VRAM_PRESSURE", "TEX_RELEASED_MB", "TEX_RELEASED_MAX", "TEX_REUSE", "TEX_SPLIT_FILL", "TEX_COMMIT_FREE_MB", "TEX_PROC_COMMIT_MB", "TEX_EVICT", "TEX_COMMIT_EVICT", "MIRROR_EVICT", "VRAM_BUDGET_MB", "TIMER_1MS", "TRACE", "TXD_TRANSPOSE", "UBO_SNAPSHOT", "EVO_TRACE", "EVENT_AT_SYNC", "UPSCALER", "VK_DYN_A2C", "VK_DYN_VERTEX", "VK_NAN_PRESERVE", "VK_NOOPT", "VK_NO_FLOAT64", "VK_PRESENT", "VK_RECONVERGE", "VK_NAN_BITS", "VK_RECORDER", "VK_SSBO_ALIGN", "VK_SUBGROUP", "VK_SUBGROUP_PIN", "VK_VALIDATION", "VOLUME", "VRAM_HEADROOM", "VS_OUTS", "WATER_PROJECTIVE", "WAIT_WATCH_S", "WALK_KEY", "WALK_SCALE", "WB_EXACT", "WB_FENCE_LIMIT", "WB_MERGE", "WB_NO_REUP", "WB_MERGE_MAX", "WB_PROBE", "WB_SPLIT", "WB_LAZY", "WB_LAZY_CHUNK", "WB_LAZY_TOUCH", "WINDOW_SIZE", "XLATE", "XLATE_ID", "XLATE_KEEP", "XLATE_PROCS", + "UPLOAD_BATCH_MB", "VRAM_HEAP_LIMIT", "VRAM_RESERVE_MB", "TEX_CLOBBER", "ZSTD_CHECK", "ZSTD_NATIVE", "BIND_REUSE", "DYN_DELTA", "STG_ARENA", "SUBMIT_BATCH", "ASTC_GPU_DESWIZZLE", "ASTC_SCRATCH_KEEP", "ASTC_ARENA", "ASTC_BC1", "TEXUP_LOG_MS", "DYN_RES", "DYN_RES_TARGET", "DYN_RES_STEP", "TEXTURE_DETAIL", @@ -88,6 +90,8 @@ static const char *const known[] = { // The nx2navi.ini section a key cfg_set may write goes to when the file lacks it (nx2navi.ini.example's sections). static const struct { const char *key, *section; } sections[] = { + // the menu's Lama patches tab (ui/menu.cpp tab_lama) + {"GUEST_OPT", "performance"}, {"PASS_TIMES", "diagnostics"}, {"DUMP_KEY", "diagnostics"}, {"FPS_LIMIT", "frame rate"}, {"FPS60", "frame rate"}, {"RTSS", "frame rate"}, {"REALTIME", "frame rate"}, {"CLOTH_REALTIME", "frame rate"}, {"HIGHFPS_FIX", "frame rate"}, {"PHYSICS_STEPS", "frame rate"}, {"PICKUP_COUNT", "frame rate"}, {"STEP_STEADY", "frame rate"}, @@ -293,6 +297,12 @@ static const CfgMeta metas[] = { // all|: the compute pipelines the boot keeps, those dispatched most recently (vk_pipeline.c, compute-used.bin) {"COMPUTE_KEEP", "512", NULL, RESTART}, {"SHADER_CARRY", "1", "0|1", RESTART}, // gfx_shader.c "Carry": a previous translator's translations until translated again + // the menu's Lama patches tab (ui/menu.cpp tab_lama): the settings of the RX 580 patches + {"TEX_RELEASED_MAX", "", NULL, RESTART}, // vk_texture.c released_max: "" by the video memory budget, else 1..16384 + {"MIRROR_HOT", "25", "0..1000", RESTART}, {"FREEZE_IDLE", "1800", "0..100000", RESTART}, + {"VRAM_HEAP_LIMIT", "auto", NULL, RESTART}, // vk_device.c vram_heap_limits: auto, 0 or MiB + {"UPLOAD_BATCH_MB", "256", NULL, RESTART}, // vk_memory.c: MiB of staging before a batch goes early, 0 no limit + {"PASS_TIMES", "0", "0|1", RESTART}, {"DUMP_KEY", "", NULL, RESTART}, // vk_crumbs.c, vk_dump.c // textures and memory {"ASTC", "auto", "auto|gpu|native|cpu", RESTART}, {"MEMORY", "auto", "auto|import|mirror|verify", RESTART}, {"TEX_ALIAS", "1", "0|1", RESTART}, {"DEPTH_INIT_INLINE", "1", "0|1", RESTART}, {"DEPTH_ALIAS_LOG", "0", "0|1", RESTART}, {"TEX_DISUSE", "1", "0|1|2", RESTART}, {"TEX_DISUSE_EVICT", "0", "0|1", RESTART}, {"TEX_GEN_UNDO", "1", "0|1", RESTART}, {"TEX_REUSE", "1", "0|1", RESTART}, {"TEX_SPLIT_FILL", "1", "0|1|2", RESTART}, {"TEX_VRAM_PRESSURE", "80", "0..100", RESTART}, {"ASTC_BC", "", "0|1", RESTART}, {"ZSTD_NATIVE", "1", "0|1", RESTART}, {"ZSTD_CHECK", "0", "0|1", RESTART}, diff --git a/runtime/ui/menu.cpp b/runtime/ui/menu.cpp index e318b28e..eabd4e64 100644 --- a/runtime/ui/menu.cpp +++ b/runtime/ui/menu.cpp @@ -83,6 +83,7 @@ int vk_fg4_failed(void); // ... it failed in this run, FSR 3.1's 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) double frame_step_limit_hz(void); int frame_limit_adjustable(void); int rtss_limit_state(void); @@ -504,7 +505,7 @@ static int fonts_up(float scale) { // what the title face shows in the CJK languages: the menu's title and tabs (Simplified Chinese menu text) and // the boot screen's title (the game's language) static const UiTextId titles[] = {UI_MENU_TITLE, UI_MENU_TAB_SCREEN, UI_MENU_TAB_GAME, UI_MENU_TAB_SOUND, - UI_MENU_TAB_CONTROLS, UI_MENU_TAB_COOP, UI_BOOT_TITLE}; + UI_MENU_TAB_CONTROLS, UI_MENU_TAB_LAMA, UI_MENU_TAB_COOP, UI_BOOT_TITLE}; for (int i = 0; i < N; i++) { if (!data[i]) continue; ImFontGlyphRangesBuilder b; @@ -572,8 +573,8 @@ extern "C" void menu_vk_release(void) { // NX2NAVI_ prefix optional) puts the cursor on that setting's row and scrolls it into view when the row is next drawn // (opt_focus_key), so a page's shot shows a row below the first screenful; it does not switch tabs. COOP_PAGE, COOP_JOIN // and COOP_ACCEPT_OFFER drive the Co-op tab (ui/coop_page.h coop_test_set). -// Ocarina of Time: the options this port has and co-op (ui/coop_page.cpp) -enum { TAB_SCREEN, TAB_GAME, TAB_SOUND, TAB_CONTROLS, TAB_COOP, TAB_COUNT }; +// Ocarina of Time: the options this port has, co-op (ui/coop_page.cpp) and the Lama patches tab (the RX 580 patches) +enum { TAB_SCREEN, TAB_GAME, TAB_SOUND, TAB_CONTROLS, TAB_LAMA, TAB_COOP, TAB_COUNT }; // co-op last: tabs_shown enum { TEST_PAGE_FRAMES = 30, TEST_SETS = 16, TEST_OPENS = 8 }; struct TestSet { uint64_t frame; char key[64], value[64]; }; static struct { @@ -1623,8 +1624,52 @@ static void tab_coop(float scale) { coop_after_page(scale); } +// ---- the Lama patches tab: the settings the RX 580 patches add (apply_rx580_fix), each read where its patch reads it +static void tab_lama(float scale) { + opt_begin("##lama", scale); + opt_text(UI_MENU_LAMA_INTRO); + opt_group(UI_MENU_LAMA_MEMORY); + { // vk_texture.c sweep_released + static const char *const values[] = {"", "512", "1024", "2048", "4096", "8192"}; + const char *names[] = {menu_text(UI_MENU_AUTO), "512", "1024", "2048", "4096", "8192"}; + opt_choice_list("NX2NAVI_TEX_RELEASED_MAX", UI_MENU_LAMA_RELEASED, values, names, 6, UI_MENU_LAMA_RELEASED_DESC); + opt_slider("NX2NAVI_MIRROR_HOT", UI_MENU_LAMA_MIRROR_HOT, 0, 100, UI_MENU_LAMA_MIRROR_HOT_DESC, 5, "%.0f %%"); + { // vk_device.c vram_heap_limits + static const char *const values[] = {"auto", "0"}; + const char *names[] = {menu_text(UI_MENU_AUTO), menu_text(UI_MENU_OFF)}; + opt_choice_list("NX2NAVI_VRAM_HEAP_LIMIT", UI_MENU_LAMA_HEAP_LIMIT, values, names, 2, UI_MENU_LAMA_HEAP_LIMIT_DESC); + { // vk_memory.c upload_batch_cap + static const char *const values[] = {"128", "256", "512", "1024", "0"}; + const char *names[] = {"128 MB", "256 MB", "512 MB", "1024 MB", menu_text(UI_MENU_LAMA_NO_LIMIT)}; + opt_choice_list("NX2NAVI_UPLOAD_BATCH_MB", UI_MENU_LAMA_UPLOAD_BATCH, values, names, 5, UI_MENU_LAMA_UPLOAD_BATCH_DESC); + opt_toggle("NX2NAVI_ASTC_SCRATCH_KEEP", UI_MENU_LAMA_ASTC_KEEP, UI_MENU_LAMA_ASTC_KEEP_DESC); + opt_group(UI_MENU_LAMA_RENDER); + const bool native = vk_mesh_shader_native() != 0; // vk_exec_draw.c: the emulation only where the GPU lacks them + opt_toggle("NX2NAVI_MESH_EMULATION", UI_MENU_LAMA_MESH_EMU, UI_MENU_LAMA_MESH_EMU_DESC); + } + opt_slider("NX2NAVI_MESH_EMU_MB", UI_MENU_LAMA_MESH_MB, 64, 2048, UI_MENU_LAMA_MESH_MB_DESC, 64, "%.0f MB"); + opt_slider("NX2NAVI_MESH_EMU_TASKS", UI_MENU_LAMA_MESH_TASKS, 4096, 65536, UI_MENU_LAMA_MESH_TASKS_DESC, 4096, "%.0f"); + opt_toggle("NX2NAVI_TEX_CLOBBER", UI_MENU_LAMA_CLOBBER, UI_MENU_LAMA_CLOBBER_DESC); + static const UiTextId vec[] = {UI_MENU_OFF, UI_MENU_LAMA_VEC_AUTO, UI_MENU_ON}; // gfx_shader.c patch_vec_index + opt_choice("NX2NAVI_VEC_INDEX_FIX", UI_MENU_LAMA_VEC_INDEX, vec, 3, UI_MENU_LAMA_VEC_INDEX_DESC); + opt_group(UI_MENU_LAMA_BUILD); + // tools/make_game.py reads it from nx2navi.ini at the next Rebuild the Game (guest_opt_ini) + opt_toggle_value("NX2NAVI_GUEST_OPT", UI_MENU_LAMA_GUEST_OPT, UI_MENU_LAMA_GUEST_OPT_DESC, "2", "1", + menu_text(UI_MENU_LAMA_GUEST_OPT_NOTE)); + opt_group(UI_MENU_LAMA_DIAG); + opt_toggle("NX2NAVI_PASS_TIMES", UI_MENU_LAMA_PASS_TIMES, UI_MENU_LAMA_PASS_TIMES_DESC); // vk_crumbs.c +#ifdef _WIN32 + { // vk_dump.c: the keys it knows + static const char *const values[] = {"", "pause", "scrolllock", "insert", "f12"}; + const char *names[] = {menu_text(UI_MENU_OFF), "Pause", "Scroll Lock", "Insert", "F12"}; + opt_choice_list("NX2NAVI_DUMP_KEY", UI_MENU_LAMA_DUMP_KEY, values, names, 5, UI_MENU_LAMA_DUMP_KEY_DESC); + } +#endif + opt_end(); +} + static const UiTextId kTabNames[TAB_COUNT] = {UI_MENU_TAB_SCREEN, UI_MENU_TAB_GAME, UI_MENU_TAB_SOUND, - UI_MENU_TAB_CONTROLS, UI_MENU_TAB_COOP}; + UI_MENU_TAB_CONTROLS, UI_MENU_TAB_LAMA, UI_MENU_TAB_COOP}; static int g_tab; // the tab shown // The tabs the menu shows: the Co-op tab is a beta, shown only with coop_beta = 1 in nx2navi.ini (NX2NAVI_COOP_BETA), @@ -1751,6 +1796,7 @@ static void layout_menu(uint32_t w, uint32_t h, float scale) { case TAB_SOUND: tab_sound(scale); break; case TAB_CONTROLS: tab_controls(scale); break; case TAB_COOP: tab_coop(scale); break; + case TAB_LAMA: tab_lama(scale); break; } ImGui::EndTabItem(); } diff --git a/runtime/ui_text.c b/runtime/ui_text.c index 9f7402bc..ed89bbe4 100644 --- a/runtime/ui_text.c +++ b/runtime/ui_text.c @@ -89,6 +89,59 @@ static const char *const text_en[UI_TEXT_COUNT] = { [UI_MENU_TEX_DETAIL_DESC] = "Sharpness of large surface textures. Reduced and Low leave out their largest versions, so that an area fits the video memory of 6 and 8 GB cards; only surfaces seen up close look softer. Automatic picks by the card's video memory.", [UI_MENU_TEX_DETAIL_AUTO] = "Automatic: %s", [UI_MENU_TEX_DETAIL_FULL] = "Full", [UI_MENU_TEX_DETAIL_REDUCED] = "Reduced", [UI_MENU_TEX_DETAIL_LOW] = "Low", + [UI_MENU_TAB_LAMA] = "Lama patches", + [UI_MENU_LAMA_INTRO] = "Settings of the RX 580 patches (apply_rx580_fix). Most take effect after a restart.", + [UI_MENU_LAMA_MEMORY] = "Video memory and textures", + [UI_MENU_LAMA_RENDER] = "Rendering", + [UI_MENU_LAMA_BUILD] = "Build", + [UI_MENU_LAMA_DIAG] = "Diagnostics", + [UI_MENU_LAMA_RELEASED] = "Released textures kept", + [UI_MENU_LAMA_RELEASED_DESC] = "How many textures the game has released are kept as they are; past it only those that " + "lose nothing when dropped go. Fewer leaves more video memory for the rest; more " + "saves making them again; too few lets some blink black for a moment. Auto: one per 2 MB " + "of the video memory budget, 2048 to 8192.", + [UI_MENU_LAMA_CLOBBER] = "Fix overwritten textures", + [UI_MENU_LAMA_CLOBBER_DESC] = "A texture the game reads after another image was drawn over its memory gets memory of " + "its own. Fixes the teal splotches in Kokiri Forest's fog.", + [UI_MENU_LAMA_MIRROR_HOT] = "Pools copied every frame stay in system memory", + [UI_MENU_LAMA_MIRROR_HOT_DESC] = "A game memory pool whose copies to and from video memory each frame reach this " + [UI_MENU_LAMA_HEAP_LIMIT] = "Video memory heap limit", + [UI_MENU_LAMA_HEAP_LIMIT_DESC] = "Auto: on GPUs with a second video memory heap (an RX 580 shows 6 GB and 2 GB), " + "each heap is filled only to its budget before the next one is used, so the " + "driver does not run out. Off: no limit.", + [UI_MENU_LAMA_UPLOAD_BATCH] = "Upload batch limit", + [UI_MENU_LAMA_UPLOAD_BATCH_DESC] = "Texture uploads waiting in staging memory are sent to the GPU early once they " + "hold this much, so an area load cannot run video memory out.", + [UI_MENU_LAMA_NO_LIMIT] = "No limit", + [UI_MENU_LAMA_ASTC_KEEP] = "Keep the ASTC decode buffer", + [UI_MENU_LAMA_ASTC_KEEP_DESC] = "The buffer that GPU-decodes compressed textures is kept between upload batches " + "instead of being allocated again for each one.", + [UI_MENU_LAMA_MESH_EMU] = "Mesh shader emulation", + [UI_MENU_LAMA_MESH_EMU_DESC] = "Draws grass, moss and other foliage on GPUs without mesh shaders (AMD RX 400/500 " + "and Vega, GTX 10-series and older), with compute shaders. GPUs with mesh shaders " + "ignore it.", + [UI_MENU_LAMA_MESH_NATIVE] = "this GPU has mesh shaders", + [UI_MENU_LAMA_MESH_MB] = "Mesh emulation memory", + [UI_MENU_LAMA_MESH_MB_DESC] = "Video memory for the emulated meshes' vertices and indices, in MB.", + [UI_MENU_LAMA_MESH_TASKS] = "Mesh emulation task records", + [UI_MENU_LAMA_MESH_TASKS_DESC] = "Task records per submission for the emulated meshes. Raise it when the log reports " + "that a submission asked for more.", + [UI_MENU_LAMA_VEC_INDEX] = "Vector index fix", + [UI_MENU_LAMA_VEC_INDEX_DESC] = "Shaders read uniform vector components at computed indices whole and select the " + "component, for drivers that get such reads wrong. Auto: on AMD's own drivers.", + [UI_MENU_LAMA_VEC_AUTO] = "Auto (AMD)", + [UI_MENU_LAMA_GUEST_OPT] = "Optimised game code (-O2)", + [UI_MENU_LAMA_GUEST_OPT_DESC] = "The next Rebuild the Game in the launcher compiles the game's code at -O2 instead " + "of -O1: the game's own threads run faster on a slower CPU. The build takes " + "several times longer.", + [UI_MENU_LAMA_GUEST_OPT_NOTE] = "at the next rebuild", + [UI_MENU_LAMA_PASS_TIMES] = "Pass times in the log", + [UI_MENU_LAMA_PASS_TIMES_DESC] = "GPU time of every render pass and dispatch goes to the log, with the largest " + "viewport each kind of pass draws with. Costs a little frame time.", + [UI_MENU_LAMA_DUMP_KEY] = "Frame dump key", + [UI_MENU_LAMA_DUMP_KEY_DESC] = "Each press of this key in the game window dumps the next frame (images and the " + "frame's passes) to the dump folder, for a glitch caught while it is on screen. " + "Windows only.", [UI_MENU_SHARPNESS] = "FSR sharpness", [UI_MENU_SHARPNESS_DESC] = "How sharp FSR makes the picture. 0 turns it off.", [UI_MENU_SHARPNESS_NEEDS_FSR] = "only with AMD FSR 1 or FSR 3.1", diff --git a/runtime/ui_text.h b/runtime/ui_text.h index 9d098b1f..7857fbf3 100644 --- a/runtime/ui_text.h +++ b/runtime/ui_text.h @@ -332,6 +332,20 @@ typedef enum { UI_MENU_FRAMEGEN_MULT_UPTO, // printf: "%d", the highest multiplier this GPU and driver allow 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 Lama patches tab (ui/menu.cpp tab_lama): the settings of the RX 580 patches, English only + UI_MENU_TAB_LAMA, UI_MENU_LAMA_INTRO, UI_MENU_LAMA_MEMORY, UI_MENU_LAMA_RENDER, UI_MENU_LAMA_BUILD, + UI_MENU_LAMA_DIAG, + UI_MENU_LAMA_RELEASED, UI_MENU_LAMA_RELEASED_DESC, + UI_MENU_LAMA_CLOBBER, UI_MENU_LAMA_CLOBBER_DESC, + UI_MENU_LAMA_MIRROR_HOT, UI_MENU_LAMA_MIRROR_HOT_DESC, + UI_MENU_LAMA_UPLOAD_BATCH, UI_MENU_LAMA_UPLOAD_BATCH_DESC, UI_MENU_LAMA_NO_LIMIT, + UI_MENU_LAMA_ASTC_KEEP, UI_MENU_LAMA_ASTC_KEEP_DESC, + UI_MENU_LAMA_MESH_EMU, UI_MENU_LAMA_MESH_EMU_DESC, UI_MENU_LAMA_MESH_NATIVE, + UI_MENU_LAMA_MESH_MB, UI_MENU_LAMA_MESH_MB_DESC, UI_MENU_LAMA_MESH_TASKS, UI_MENU_LAMA_MESH_TASKS_DESC, + UI_MENU_LAMA_VEC_INDEX, UI_MENU_LAMA_VEC_INDEX_DESC, UI_MENU_LAMA_VEC_AUTO, + UI_MENU_LAMA_GUEST_OPT, UI_MENU_LAMA_GUEST_OPT_DESC, UI_MENU_LAMA_GUEST_OPT_NOTE, + UI_MENU_LAMA_PASS_TIMES, UI_MENU_LAMA_PASS_TIMES_DESC, + UI_MENU_LAMA_DUMP_KEY, UI_MENU_LAMA_DUMP_KEY_DESC, UI_TEXT_COUNT } UiTextId; diff --git a/runtime/vk_device.c b/runtime/vk_device.c index 02ca353a..9b547287 100644 --- a/runtime/vk_device.c +++ b/runtime/vk_device.c @@ -794,3 +794,6 @@ int probe_vkdevice(void) { printf("probe-vkdevice: %s (validation errors %ld)\n", g_errors_total ? "FAILED" : "passed", g_errors_total); return g_errors_total ? 1 : 0; } + +// The GPU has mesh shaders: the mesh emulation (NX2NAVI_MESH_EMULATION) does nothing there (the menu's Lama patches tab). +int vk_mesh_shader_native(void) { return g_vk.has_mesh_shader; } diff --git a/tools/make_game.py b/tools/make_game.py index 2df2f550..0f5cbe26 100644 --- a/tools/make_game.py +++ b/tools/make_game.py @@ -1425,10 +1425,29 @@ def fast_clang(msys, clang, env): return fast if mine and clang_ident(fast, env) == mine else None +def guest_opt_ini(out): + """NX2NAVI_GUEST_OPT from nx2navi.ini next to the exe (the menu's Lama patches tab writes it there) when the + environment does not set it: the next build of the game folder out takes it.""" + if os.environ.get('NX2NAVI_GUEST_OPT', '').strip(): + return + try: + for line in (Path(out) / 'nx2navi.ini').read_text(encoding='utf-8', errors='replace').splitlines(): + key, eq, value = line.partition('=') + key = key.strip().lower() + if eq and key in ('guest_opt', 'nx2navi_guest_opt'): + value = value.split('#')[0].split(';')[0].strip().strip('"') + if value: + os.environ['NX2NAVI_GUEST_OPT'] = value + except OSError: + pass + + def runtime_cmd(clang, clangxx, inc, level=0, fast=None, msys=None, first=()): """fast: fast_clang's compiler for the lifted code, with msys as its sysroot. first: include flags that go ahead of inc for the runtime's sources only (vulkan_headers); the lifted code includes none of those headers, - and its command, which is part of its objects' keys, stays as it was.""" + and its command, which is part of its objects' keys, stays as it was. NX2NAVI_GUEST_OPT (an environment variable, + or guest_opt in nx2navi.ini) 1 builds the lifted code at -O1; by default -O2: the game's own threads run it and + bound the frame on a slower CPU; the build takes several times longer.""" def cmd_for(src, dst): cpp = src.suffix in ('.cpp', '.cxx') # the lifted code at -O1 (its size makes -O2 slow to build), the runtime at -O2; neither may assume strict @@ -1721,6 +1740,7 @@ def step_compile(out, cache_dir, msys, jobs, romfs_job=None, update=False): cid, cid_old = compiler_ids(clang, env) # fast_clang's compiler writes the same objects: not part of the key now = cpu_level(clang, env) level = lifted_level(obj, now, update) + guest_opt_ini(out) if os.environ.get('NX2NAVI_GUEST_OPT', '').strip() == '2': # runtime_cmd's guest_opt say(' lifted code at -O2 (NX2NAVI_GUEST_OPT): a long build') if level == now: