Merge task/uborder: #896 (order overlapping uniform overlay copies), #859, #860, #862, #863 (checks that failed on dev)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Valiantsin DzerakhandClaude Opus 5.5 committed 2026-11-07 09:26:31 +03:00
commit 316ba63619
5 files changed
+35 -6

No files matched your search

+1
View File
@@ -74,6 +74,7 @@ Many rows below are developer tools that only act together with another setting
| `menu_test_set` | `<frame>:<key>=<value>[,...][;...]` changes settings live at that frame, with or without the menu open; `SAVE=1` also writes `totk.ini`. | Settings change during play without input, and `SAVE=1` rewrites the file. | Caution |
| `probe_movie` | Text that picks the movie for `totk.exe --probe-movie`: the first file whose path contains it. | Only used by the movie decoder probe; ignored in normal play. | Safe |
| `probe_movie_shot` | Path of a `.ppm` file that the movie probe writes the middle frame to. | Only used by the movie decoder probe. | Safe |
| `probe_movie_bench` | `1` makes the movie probe also time the resampler that fits a movie to a game resolution of another shape, and print the time per frame. | Only used by the movie decoder probe. | Safe |
| `swkbd_answer` | `<text>`, `<cancel>` or `<initial>`: answers the on-screen keyboard (for example a horse name) without opening a window. | The game gets that answer every time it asks for text. | Caution |
| `swkbd_test` | `ok` or `cancel` opens the keyboard window and presses OK or Cancel on the first timer tick. | The keyboard window closes by itself. | Caution |
| `test_pad` | `<lx>,<ly>,<rx>,<ry>` attaches a virtual gamepad whose sticks rest at these raw SDL axis values (-32768 to 32767). | The game sees a controller with that drift or deflection; a malformed value is logged and ignored. | Caution |
+7 -1
View File
@@ -929,8 +929,14 @@ static void probe_menu_text(void) {
cfg_set("TOTK_MENU_LANG", "zh-Hans");
CHECK(menu_text(UI_MENU_TITLE) == ui_text_in("zh-Hans", UI_MENU_TITLE), "menu_text ignores MENU_LANG=zh-Hans");
cfg_set("TOTK_MENU_LANG", "");
// the system language as ui_text.c resolve_menu_lang takes it: the tag, else its base language (ru-RU: ru), else en
const char *sys_lang = ui_text_lang(plat_ui_language());
const char *auto_lang = ui_text_defined(sys_lang, UI_MENU_TITLE) ? sys_lang : "en";
char sys_base[16] = "";
size_t base_n = strcspn(sys_lang, "-");
if (sys_lang[base_n] && base_n < sizeof sys_base) memcpy(sys_base, sys_lang, base_n);
const char *auto_lang = ui_text_defined(sys_lang, UI_MENU_TITLE) ? sys_lang
: *sys_base && ui_text_defined(sys_base, UI_MENU_TITLE) ? sys_base
: "en";
CHECK(menu_text(UI_MENU_CONTINUE) == ui_text_in(auto_lang, UI_MENU_CONTINUE), "menu_text auto ignores the system language");
}
+7
View File
@@ -1100,6 +1100,10 @@ static const char *const text_pt_br[UI_TEXT_COUNT] = {
[UI_MENU_MODE_DOCKED] = "Modo TV", [UI_MENU_MODE_HANDHELD] = "Modo portátil",
[UI_MENU_VOLUME] = "Volume", [UI_MENU_VOLUME_DESC] = "Volume geral do jogo.",
[UI_MENU_AUDIO_CHANNELS] = "Alto-falantes",
[UI_MENU_AUDIO_CHANNELS_DESC] = "Saída estéreo ou surround 5.1. Automático escolhe 5.1 quando a configuração de "
"alto-falantes do Windows tem seis canais ou mais. Vale após reiniciar.",
[UI_MENU_CHANNELS_AUTO] = "Automático", [UI_MENU_CHANNELS_STEREO] = "Estéreo", [UI_MENU_CHANNELS_51] = "Surround 5.1",
[UI_MENU_MOTION] = "Controles de movimento", [UI_MENU_MOTION_DESC] = "Mirar com o giroscópio do controle.",
[UI_MENU_RUMBLE_STRENGTH] = "Intensidade da vibração",
@@ -1647,6 +1651,9 @@ static const char *const text_zh_hans[UI_TEXT_COUNT] = {
"这样被打断的读取可能会永久卡住。",
[UI_MENU_VOLUME] = "音量",
[UI_MENU_VOLUME_DESC] = "游戏的主音量。",
[UI_MENU_AUDIO_CHANNELS] = "扬声器",
[UI_MENU_AUDIO_CHANNELS_DESC] = "立体声或 5.1 环绕声输出。选择自动时,若 Windows 扬声器设置有六个或更多声道则使用 5.1。重启后生效。",
[UI_MENU_CHANNELS_AUTO] = "自动", [UI_MENU_CHANNELS_STEREO] = "立体声", [UI_MENU_CHANNELS_51] = "5.1 环绕声",
[UI_MENU_MOTION] = "体感操作",
[UI_MENU_MOTION_DESC] = "用手柄的陀螺仪瞄准。",
[UI_MENU_RUMBLE_STRENGTH] = "振动强度",
+19 -4
View File
@@ -175,7 +175,7 @@ static struct {
struct { uint64_t dst; VkBuffer src; VkDeviceSize soff; VkMemSpan sp; uint64_t size; } p[OV_N]; // to copy
struct { uint64_t lo, hi; } f[OV_FOREIGN]; // GPU writes of other kinds
// since the last perf line (vk_exec_ub_perf)
uint64_t c_update, c_overlaid, c_flush, c_bind, c_merged, c_mixed, c_inpass, c_outside, c_early;
uint64_t c_update, c_overlaid, c_flush, c_bind, c_merged, c_mixed, c_inpass, c_outside, c_early, c_order;
} OV = {.mode = -1};
// A binding without a size reaches to the end of its backing: as far as the overlays go, for ov_at.
@@ -3349,7 +3349,22 @@ void vk_exec_ub_flush(VkExec *ex) {
VkDependencyInfo di = {.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .memoryBarrierCount = 1, .pMemoryBarriers = &mb};
vkCmdPipelineBarrier2(ex->cb, &di);
ex->recorded++;
// Copies without a barrier between them may run in any order, and ov_add only drops an older copy of exactly the
// same range: a copy that overlaps one recorded since the last barrier waits for it, so the newer bytes land last.
VkMemoryBarrier2 ww = {.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
.srcStageMask = VK_PIPELINE_STAGE_2_COPY_BIT, .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT,
.dstStageMask = VK_PIPELINE_STAGE_2_COPY_BIT, .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT};
VkDependencyInfo wdi = {.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .memoryBarrierCount = 1, .pMemoryBarriers = &ww};
uint32_t since = 0; // the first copy recorded after the last barrier
for (uint32_t i = 0; i < OV.np; i++) {
for (uint32_t k = since; k < i; k++)
if (OV.p[i].dst < OV.p[k].dst + OV.p[k].size && OV.p[k].dst < OV.p[i].dst + OV.p[i].size) {
vkCmdPipelineBarrier2(ex->cb, &wdi);
ex->recorded++;
OV.c_order++;
since = i;
break;
}
VkBufferCopy cp = {OV.p[i].soff, OV.p[i].sp.offset, OV.p[i].size};
vkCmdCopyBuffer(ex->cb, OV.p[i].src, OV.p[i].sp.buffer, 1, &cp);
ex->recorded++;
@@ -3365,11 +3380,11 @@ void vk_exec_ub_perf(void) {
const double k = 1 / 600.0;
rt_log("perf: uniform updates per submission %.1f: %.1f overlaid in a pass (copied in %.2f batches), %.1f copied "
"in a pass, %.1f outside one; bindings from an overlay %.1f (%.1f merged, %.1f over other GPU writes), %.2f "
"batches brought forward for a storage write",
"batches brought forward for a storage write, %.2f barriers between overlapping copies",
OV.c_update * k, OV.c_overlaid * k, OV.c_flush * k, OV.c_inpass * k, OV.c_outside * k, OV.c_bind * k,
OV.c_merged * k, OV.c_mixed * k, OV.c_early * k);
OV.c_merged * k, OV.c_mixed * k, OV.c_early * k, OV.c_order * k);
OV.c_update = OV.c_overlaid = OV.c_flush = OV.c_bind = OV.c_merged = OV.c_mixed = 0;
OV.c_inpass = OV.c_outside = OV.c_early = 0;
OV.c_inpass = OV.c_outside = OV.c_early = OV.c_order = 0;
}
// The scratch bytes of a uniform or storage binding [addr, addr+n) an overlay of this submission touches: 1 with *out
+1 -1
View File
@@ -18,7 +18,7 @@ ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / 'tools'))
import worktree # noqa: E402
IGNORED = '\n'.join('/' + d + '/' for d in worktree.LINK_DIRS) + '\n/' + worktree.LINK_FILES[0] + '\n/.worktrees/\n'
IGNORED = ''.join(f'/{p}\n' for p in [d + '/' for d in worktree.LINK_DIRS] + worktree.LINK_FILES + ['.worktrees/'])
def git(cwd, *a):