fix(vk): upload ASTC textures re-encoded as BC3 over several submissions (#900 rebased) #1130

Open
metroid98 wants to merge 7 commits from metroid98/fix/bc3-multi-submission-rebase into main
metroid98 commented 2026-11-09 13:35:39 +00:00 (Migrated from github.com)

This is #900 by @ZurielAtr, rebased onto current main because it was closed only for conflicts ("please rebase on current main and reopen"). Their commit is kept as is (authorship preserved); the conflict resolution is part of that cherry-picked commit. The original description and hardware test (RX 7700S, Windows 11, Adrenalin 26.10.1: Castle Town to Hyrule Field reset the driver 3 out of 3 times before, no reset after) are in #900.

It belongs to the AMD-on-Windows tracker #996 ("device lost after minutes of play"). It has no Fixes line, because the original did not have one.

What was resolved

Two conflicts, nothing else changed:

  • tests/run_all.py: kept main's three newer ARGS entries and added tests/test_bc_parts.py. The original workflow-file registration is not needed, since the runner discovers tests.
  • gpu/vk/vk_texture.cpp: the #include list (kept main's includes plus bc_parts.h), and the layer-run loop in upload_astc_gpu. Since #900, main made BC3 uploads one layer a run by default (RX_VK_BC_LAYERS, default 1, to stop the dark lines on Hyrule Field's terrain). The loop now takes its run length from that same run value, passed to bc_parts::run_end instead of kBcLayers, so main's behaviour is kept and only the per-recording budget (RX_VK_BC_PART_MTEXELS) is added.

tests/test_bc_parts.py's source checks still match the resolved files (I compared the needles by reading).

Not run

Nothing was compiled or run locally: this was code-only work and no tests, game or build were executed. The behaviour is the original author's tested one; only the merge was done here. It needs a build, tests/run_all.py, and ideally a repeat of the Castle Town to Hyrule Field test on AMD, with the one-layer-a-run default in place.

AI-assisted (Claude Code) on behalf of metroid98.

🤖 Generated with Claude Code

https://claude.ai/code/session_015DmSMGJSY9hHswALy4eqtQ

This is #900 by @ZurielAtr, rebased onto current main because it was closed only for conflicts ("please rebase on current main and reopen"). Their commit is kept as is (authorship preserved); the conflict resolution is part of that cherry-picked commit. The original description and hardware test (RX 7700S, Windows 11, Adrenalin 26.10.1: Castle Town to Hyrule Field reset the driver 3 out of 3 times before, no reset after) are in #900. It belongs to the AMD-on-Windows tracker #996 ("device lost after minutes of play"). It has no `Fixes` line, because the original did not have one. ## What was resolved Two conflicts, nothing else changed: - `tests/run_all.py`: kept main's three newer `ARGS` entries and added `tests/test_bc_parts.py`. The original workflow-file registration is not needed, since the runner discovers tests. - `gpu/vk/vk_texture.cpp`: the `#include` list (kept main's includes plus `bc_parts.h`), and the layer-run loop in `upload_astc_gpu`. Since #900, main made BC3 uploads one layer a run by default (`RX_VK_BC_LAYERS`, default 1, to stop the dark lines on Hyrule Field's terrain). The loop now takes its run length from that same `run` value, passed to `bc_parts::run_end` instead of `kBcLayers`, so main's behaviour is kept and only the per-recording budget (`RX_VK_BC_PART_MTEXELS`) is added. `tests/test_bc_parts.py`'s source checks still match the resolved files (I compared the needles by reading). ## Not run Nothing was compiled or run locally: this was code-only work and no tests, game or build were executed. The behaviour is the original author's tested one; only the merge was done here. It needs a build, `tests/run_all.py`, and ideally a repeat of the Castle Town to Hyrule Field test on AMD, with the one-layer-a-run default in place. AI-assisted (Claude Code) on behalf of metroid98. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_015DmSMGJSY9hHswALy4eqtQ
Nitnek commented 2026-11-09 15:51:26 +00:00 (Migrated from github.com)

Tested on NVIDIA (RTX 3070 8 GB, Windows 11), merged onto v2.0.8-rc.5, with a scripted run: load the Hyrule Castle autosave, turn the camera.

  • The new path runs here: BC3 texture … 1365x1365 x90: 89 of 90 layers left for the next recordings, 20 such lines.
  • The picture matches rc.5. No device lost; no new warnings.
  • Frame times (RX_VK_FRAME_LOG), two runs each, from the save's confirm screen into play:
    • the load hitch is 2158 / 2052 ms with this PR, against 823 / 908 ms on rc.5;
    • p50 and p99 are unchanged (about 18 / 36-40 ms).
      So on this card the castle load stalls about 1.2 s longer. That is perhaps the price of spreading the 90-layer arrays over several recordings. Gating the per-recording budget to AMD, or raising it on NVIDIA, might avoid it.
Tested on NVIDIA (RTX 3070 8 GB, Windows 11), merged onto v2.0.8-rc.5, with a scripted run: load the Hyrule Castle autosave, turn the camera. - The new path runs here: `BC3 texture … 1365x1365 x90: 89 of 90 layers left for the next recordings`, 20 such lines. - The picture matches rc.5. No device lost; no new warnings. - Frame times (`RX_VK_FRAME_LOG`), two runs each, from the save's confirm screen into play: - the load hitch is **2158 / 2052 ms with this PR, against 823 / 908 ms on rc.5**; - p50 and p99 are unchanged (about 18 / 36-40 ms). So on this card the castle load stalls about 1.2 s longer. That is perhaps the price of spreading the 90-layer arrays over several recordings. Gating the per-recording budget to AMD, or raising it on NVIDIA, might avoid it.
metroid98 commented 2026-11-09 15:53:29 +00:00 (Migrated from github.com)

Thanks @Nitnek, that's exactly the data this needed. Pushed b7f5525: the per-recording budget now defaults to AMD only (dev.props.vendorID == 0x1002, the same check vk_draw.cpp uses). Other GPUs default to 0, meaning all at once as before, so NVIDIA should be back to rc.5's load hitch. RX_VK_BC_PART_MTEXELS still overrides it on any GPU. Not built locally. A re-run of your castle script on the 3070 would confirm the hitch is back to ~0.9 s.

(AI-assisted via Claude Code on my behalf.)

Thanks @Nitnek, that's exactly the data this needed. Pushed b7f5525: the per-recording budget now defaults to AMD only (`dev.props.vendorID == 0x1002`, the same check `vk_draw.cpp` uses). Other GPUs default to 0, meaning all at once as before, so NVIDIA should be back to rc.5's load hitch. `RX_VK_BC_PART_MTEXELS` still overrides it on any GPU. Not built locally. A re-run of your castle script on the 3070 would confirm the hitch is back to ~0.9 s. (AI-assisted via Claude Code on my behalf.)
hckrman101 commented 2026-11-09 18:39:51 +00:00 (Migrated from github.com)

Hi! This PR has merge conflicts with main now (a lot has landed today). Could you merge main in or rebase and resolve them? Happy to give it a proper review once it's up to date.

Hi! This PR has merge conflicts with `main` now (a lot has landed today). Could you merge `main` in or rebase and resolve them? Happy to give it a proper review once it's up to date.
metroid98 commented 2026-11-09 18:46:47 +00:00 (Migrated from github.com)

Merged main in (only tests/run_all.py conflicted: kept both test_output_resolution.py and test_bc_parts.py). GitHub now reports it as mergeable. Thanks for the heads-up. (AI-assisted via Claude Code on my behalf.)

Merged `main` in (only `tests/run_all.py` conflicted: kept both `test_output_resolution.py` and `test_bc_parts.py`). GitHub now reports it as mergeable. Thanks for the heads-up. (AI-assisted via Claude Code on my behalf.)
lucasmazzoni45-del commented 2026-11-09 21:00:17 +00:00 (Migrated from github.com)

Test result from an AMD card, since this PR defaults to AMD only and the one test above was on NVIDIA (where it is off): on an RX 7800 XT the default of 16 M texels a recording showed large blocks of wrong colour in the sky, and they went away with RX_VK_BC_PART_MTEXELS=0. One observation, so please take it as a lead and not a verdict.

Setup: RX 7800 XT 16 GB, Ryzen 7 5800X3D, Windows 11, driver 0x8001a0 as Vulkan reports it, v2.0.11 with this PR merged by hand on top (see the caveat), 2560x1440, frame generation x2, normal play. The log line for the split path appears (BC3 texture 0x109538a600 1365x1365 x90: 87 of 90 layers left for the next recordings (1 so far), then 84, 81, 78 ... up to the 20 lines the log prints).

What I saw, about 11 minutes after start, standing in Castle Town below the ruined castle: big square blocks, black, purple, yellow and red, over the sky (and over the top-left corner behind the HUD), with a stepped outline like wrong BC blocks. Two screenshots 0.7 s apart were identical (the fairy and the flames moved, the blocks did not), so it is a texture that stayed wrong, not an interpolated frame.

I then set only RX_VK_BC_PART_MTEXELS=0 (everything at once, as before) and restarted; the sky was clean in the same place. I have only about 2 minutes of play since, so I will repeat it for a longer session before calling it confirmed.

Caveats:

  • My build is v2.0.11 plus this PR plus some AMD changes of mine (a larger image-pool preallocation, a batched write-back from #840, the pipeline cache read over 2 GB), so I cannot rule out an interaction with those. The setting I changed is the only difference between the clean and the broken run.
  • I do not know which texture was wrong. The only deferred texture in the log is the 1365x1365 x90 array, and I did not check whether the sky is made from it. If it helps I can log RX_VK_LOG_MADE/RX_VK_LOG_UPLOADS the next time it happens.
  • I did not see a device lost or a long stall either way.

If there is a place where a deferred layer can be skipped (a texture used again, or made again, before texture_bc_continue gets to it), that would fit what I saw. Happy to test a build on this card.

Test result from an AMD card, since this PR defaults to AMD only and the one test above was on NVIDIA (where it is off): **on an RX 7800 XT the default of 16 M texels a recording showed large blocks of wrong colour in the sky, and they went away with `RX_VK_BC_PART_MTEXELS=0`.** One observation, so please take it as a lead and not a verdict. Setup: RX 7800 XT 16 GB, Ryzen 7 5800X3D, Windows 11, driver 0x8001a0 as Vulkan reports it, v2.0.11 with this PR merged by hand on top (see the caveat), 2560x1440, frame generation x2, normal play. The log line for the split path appears (`BC3 texture 0x109538a600 1365x1365 x90: 87 of 90 layers left for the next recordings (1 so far)`, then 84, 81, 78 ... up to the 20 lines the log prints). What I saw, about 11 minutes after start, standing in Castle Town below the ruined castle: big square blocks, black, purple, yellow and red, over the sky (and over the top-left corner behind the HUD), with a stepped outline like wrong BC blocks. Two screenshots 0.7 s apart were identical (the fairy and the flames moved, the blocks did not), so it is a texture that stayed wrong, not an interpolated frame. I then set only `RX_VK_BC_PART_MTEXELS=0` (everything at once, as before) and restarted; the sky was clean in the same place. I have only about 2 minutes of play since, so I will repeat it for a longer session before calling it confirmed. Caveats: - My build is v2.0.11 plus this PR plus some AMD changes of mine (a larger image-pool preallocation, a batched write-back from #840, the pipeline cache read over 2 GB), so I cannot rule out an interaction with those. The setting I changed is the only difference between the clean and the broken run. - I do not know which texture was wrong. The only deferred texture in the log is the 1365x1365 x90 array, and I did not check whether the sky is made from it. If it helps I can log `RX_VK_LOG_MADE`/`RX_VK_LOG_UPLOADS` the next time it happens. - I did not see a device lost or a long stall either way. If there is a place where a deferred layer can be skipped (a texture used again, or made again, before `texture_bc_continue` gets to it), that would fit what I saw. Happy to test a build on this card.
metroid98 commented 2026-11-09 21:09:24 +00:00 (Migrated from github.com)

Thanks @lucasmazzoni45-del, that's an important lead, since AMD is exactly where this is on by default. I've moved the PR back to draft until it's understood: as you say, with RX_VK_BC_PART_MTEXELS=0 this PR does nothing, so "clean with 0, blocks with 16" points at the split path. That could be a deferred layer run that is never re-uploaded or goes stale, or the BC scratch being reused across recordings.

I can't reproduce this without an AMD card. If a longer run confirms it, the most useful data would be whether the blocks appear only after a texture had ... layers left for the next recordings lines, and whether they persist across a scene reload. @ZurielAtr, since it's your change, you may see the cause faster than I can.

(AI-assisted via Claude Code on my behalf.)

Thanks @lucasmazzoni45-del, that's an important lead, since AMD is exactly where this is on by default. I've moved the PR back to draft until it's understood: as you say, with `RX_VK_BC_PART_MTEXELS=0` this PR does nothing, so "clean with 0, blocks with 16" points at the split path. That could be a deferred layer run that is never re-uploaded or goes stale, or the BC scratch being reused across recordings. I can't reproduce this without an AMD card. If a longer run confirms it, the most useful data would be whether the blocks appear only after a texture had `... layers left for the next recordings` lines, and whether they persist across a scene reload. @ZurielAtr, since it's your change, you may see the cause faster than I can. (AI-assisted via Claude Code on my behalf.)
lucasmazzoni45-del commented 2026-11-09 21:20:13 +00:00 (Migrated from github.com)

Thanks @metroid98 for moving it to draft and for the questions. What my log from the session with the blocks can and cannot answer:

  • Which texture had ... layers left for the next recordings lines: only one is printed, 0x109538a600 1365x1365 x90. The line is only logged for the first 20 deferrals and then every 200th, and nothing after the 20th was printed, so there were fewer than 200 deferrals in the whole session, but I cannot tell which textures deferrals 21 and up were.
  • When: all 20 printed lines are at present ~2280 (the load), 3 layers a recording (87, 84, 81 ... 30 left at the 20th line). The blocks were on screen at present ~15960, about 3.7 minutes later at 60 fps and about 11 minutes after start. So I cannot tie the blocks to the deferral of that array: it should have finished long before, unless the later, unlogged deferrals were another texture (the sky, for instance).
  • Whether they persist across a scene reload: I do not know. I took two screenshots 0.7 s apart (identical) and then restarted with RX_VK_BC_PART_MTEXELS=0; the game was a new process by then.
  • Same place after restart with the split off: clean, but only for a couple of minutes at first. I am playing longer with it off and will say here if the blocks come back.

What would settle it is one more log line when a deferred texture is finished or dropped (the bc_pending erase in the texture's destroy path), with the texture's address, so a "left" line can be matched to an "all layers in" line. I can add that to my build and re-run with the default of 16, if that is useful to you; I would rather not guess which texture it was.

Also, my build is v2.0.11 + this PR + AMD changes of mine, so it may not behave exactly like the PR on stock main.

Thanks @metroid98 for moving it to draft and for the questions. What my log from the session with the blocks can and cannot answer: - **Which texture had `... layers left for the next recordings` lines:** only one is printed, `0x109538a600 1365x1365 x90`. The line is only logged for the first 20 deferrals and then every 200th, and nothing after the 20th was printed, so there were fewer than 200 deferrals in the whole session, but I cannot tell which textures deferrals 21 and up were. - **When:** all 20 printed lines are at present ~2280 (the load), 3 layers a recording (87, 84, 81 ... 30 left at the 20th line). The blocks were on screen at present ~15960, about 3.7 minutes later at 60 fps and about 11 minutes after start. So I cannot tie the blocks to the deferral of that array: it should have finished long before, unless the later, unlogged deferrals were another texture (the sky, for instance). - **Whether they persist across a scene reload:** I do not know. I took two screenshots 0.7 s apart (identical) and then restarted with `RX_VK_BC_PART_MTEXELS=0`; the game was a new process by then. - **Same place after restart with the split off:** clean, but only for a couple of minutes at first. I am playing longer with it off and will say here if the blocks come back. What would settle it is one more log line when a deferred texture is finished or dropped (the `bc_pending` erase in the texture's destroy path), with the texture's address, so a "left" line can be matched to an "all layers in" line. I can add that to my build and re-run with the default of 16, if that is useful to you; I would rather not guess which texture it was. Also, my build is v2.0.11 + this PR + AMD changes of mine, so it may not behave exactly like the PR on stock main.
lucasmazzoni45-del commented 2026-11-09 21:27:15 +00:00 (Migrated from github.com)

Correction to my earlier report here, so nobody chases the wrong thing: square blocks came back while the split was off. With RX_VK_BC_PART_MTEXELS=0 (the log has no layers left for the next recordings line at all in this session) I saw them again about 5 minutes after start.

They do not look like the first ones, though. The first were opaque black, purple, yellow and red blocks over the sky of Castle Town. These are translucent squares, mostly greyer than the glow around them, in a grid over a very bright light shaft in a forest area (RX 7800 XT, v2.0.11, same machine). That second kind looks like #1117 (blocky light halos around bright spots, the few NEAREST samplers), not like a texture that was left half uploaded.

So what I can say now:

  • the second kind is not caused by this PR (split off, still there);
  • the first kind (opaque black/purple/yellow blocks in the sky) I have not seen again, and I cannot tell whether it was the split path, because I have not run long with the default of 16 again. Its first appearance was about 11 minutes in with the default.

I would not treat "clean with 0" as a confirmation of anything yet. Sorry for the noise.

Correction to my earlier report here, so nobody chases the wrong thing: **square blocks came back while the split was off.** With `RX_VK_BC_PART_MTEXELS=0` (the log has no `layers left for the next recordings` line at all in this session) I saw them again about 5 minutes after start. They do not look like the first ones, though. The first were opaque black, purple, yellow and red blocks over the sky of Castle Town. These are translucent squares, mostly greyer than the glow around them, in a grid over a very bright light shaft in a forest area (RX 7800 XT, v2.0.11, same machine). That second kind looks like #1117 (blocky light halos around bright spots, the few NEAREST samplers), not like a texture that was left half uploaded. So what I can say now: - the second kind is not caused by this PR (split off, still there); - the first kind (opaque black/purple/yellow blocks in the sky) I have not seen again, and I cannot tell whether it was the split path, because I have not run long with the default of 16 again. Its first appearance was about 11 minutes in with the default. I would not treat "clean with 0" as a confirmation of anything yet. Sorry for the noise.
metroid98 commented 2026-11-09 21:29:48 +00:00 (Migrated from github.com)

Thanks for the careful correction, @lucasmazzoni45-del. That makes the translucent grid look like #1117 rather than this PR. I'll keep this as a draft until someone gets a longer AMD run with the default 16 M budget and either sees the opaque sky blocks again or doesn't, then mark it ready or dig in. (AI-assisted via Claude Code on my behalf.)

Thanks for the careful correction, @lucasmazzoni45-del. That makes the translucent grid look like #1117 rather than this PR. I'll keep this as a draft until someone gets a longer AMD run with the default 16 M budget and either sees the opaque sky blocks again or doesn't, then mark it ready or dig in. (AI-assisted via Claude Code on my behalf.)
lucasmazzoni45-del commented 2026-11-09 21:30:32 +00:00 (Migrated from github.com)

Follow-up with a useful detail: the place where I first saw the opaque black/purple/yellow/red blocks (the sky of Castle Town, below the ruined castle) is clean again with RX_VK_BC_PART_MTEXELS=0. I went back to that spot in this session and the sky is fine there.

The translucent squares I mentioned in my correction are somewhere else, in a strong light shaft in the Kakariko graveyard, and I think they are #1117's blocky glow and not this PR. So the two things are separate, and the Castle Town result is consistent with my first report: the blocks there went away when the split was turned off.

Still one observation on one machine, and a few minutes in the same spot, not a long run, so I would still call it a lead. Today's log has no deferral line at all with the setting at 0; the earlier session with the default had 20 printed ones (the only texture shown was the 1365x1365 x90 array, at the load).

Follow-up with a useful detail: the place where I first saw the opaque black/purple/yellow/red blocks (the sky of Castle Town, below the ruined castle) is **clean again** with `RX_VK_BC_PART_MTEXELS=0`. I went back to that spot in this session and the sky is fine there. The translucent squares I mentioned in my correction are somewhere else, in a strong light shaft in the Kakariko graveyard, and I think they are #1117's blocky glow and not this PR. So the two things are separate, and the Castle Town result is consistent with my first report: the blocks there went away when the split was turned off. Still one observation on one machine, and a few minutes in the same spot, not a long run, so I would still call it a lead. Today's log has no deferral line at all with the setting at 0; the earlier session with the default had 20 printed ones (the only texture shown was the 1365x1365 x90 array, at the load).
metroid98 commented 2026-11-09 21:41:59 +00:00 (Migrated from github.com)

Thanks @lucasmazzoni45-del, that makes the split path the suspect for the opaque blocks. I've read through it for a cause; here's what I found:

  • Ruled out: a deferred run outliving its texture. Every removal goes through destroy_later, which drops the texture's pending entries, so a recycled Texture* can't receive another texture's layers.
  • A real hazard, fixed in 8487ee8: with RX_VK_PARALLEL > 1, segment workers pushed to bc_pending (a plain vector) while the replay thread drained it. A deferred run could also land in another segment that the queue reaches before the image's first layout change, which is the hazard the seg_init comment describes. Segment workers now upload all at once. Was RX_VK_PARALLEL set in your session? If not, this isn't your cause.
  • Expected, but maybe relevant to you: until a texture's deferred layers are in, those layers show whatever the image memory held. With your larger image-pool preallocation, that memory may be another texture's old BC blocks, which would look exactly like opaque black, purple, yellow and red squares. They should only last until the continuation runs, a few recordings. If they persist, that points at the continuation never running for those layers. The log line N of 90 layers left counting down to the end, or not, would show which.

Still a draft. Not built or run here (no AMD card).

(AI-assisted via Claude Code on my behalf.)

Thanks @lucasmazzoni45-del, that makes the split path the suspect for the opaque blocks. I've read through it for a cause; here's what I found: - **Ruled out:** a deferred run outliving its texture. Every removal goes through `destroy_later`, which drops the texture's pending entries, so a recycled `Texture*` can't receive another texture's layers. - **A real hazard, fixed in 8487ee8:** with `RX_VK_PARALLEL` > 1, segment workers pushed to `bc_pending` (a plain vector) while the replay thread drained it. A deferred run could also land in another segment that the queue reaches before the image's first layout change, which is the hazard the `seg_init` comment describes. Segment workers now upload all at once. **Was `RX_VK_PARALLEL` set in your session?** If not, this isn't your cause. - **Expected, but maybe relevant to you:** until a texture's deferred layers are in, those layers show whatever the image memory held. With your larger image-pool preallocation, that memory may be another texture's old BC blocks, which would look exactly like opaque black, purple, yellow and red squares. They should only last until the continuation runs, a few recordings. If they persist, that points at the continuation never running for those layers. The log line `N of 90 layers left` counting down to the end, or not, would show which. Still a draft. Not built or run here (no AMD card). (AI-assisted via Claude Code on my behalf.)
lucasmazzoni45-del commented 2026-11-09 21:54:53 +00:00 (Migrated from github.com)

Thanks @metroid98 for reading through it. Answers:

  • RX_VK_PARALLEL: no. It is not in hookshot_env.txt in that session or in any of my earlier copies of the file, and not in the user or machine environment. The Parallel... lines in that log are the game's own ParallelDecompThread messages, not the parallel replay. So the replay was serial and the bc_pending race in 8487ee8 is not my cause.
  • Image-pool preallocation: yes. The log of the session with the opaque blocks has images from a pool of 128 MB blocks (memory type 0), 30 made at the start, so 30 blocks (3.75 GB) were allocated up front, against the default of about 12 on this card (10% of VRAM). Your point about the deferred layers showing old BC blocks from another texture fits that; I cannot say whether the default would show them too.
  • Duration. I cannot tell you how long the blocks lasted: my two screenshots are 0.7 s apart and both show them, and I did not watch longer. The N of 90 layers left lines printed in that session are only the first 20 (the log stops printing after 20), so the countdown to the end is not in my log either; the 20 lines are all at the load (present ~2280), the blocks were on screen at present ~15960.

What I can do next without a rebuild: a longer run with the split on at the default 16 and the preallocation at the default as well, to separate "split path" from "split path with a big preallocated pool". If I rebuild, I would add a log line when a deferred texture finishes, with its address. Tell me which of the two is more useful to you; I will report here either way.

Thanks @metroid98 for reading through it. Answers: - **`RX_VK_PARALLEL`: no.** It is not in `hookshot_env.txt` in that session or in any of my earlier copies of the file, and not in the user or machine environment. The `Parallel...` lines in that log are the game's own `ParallelDecompThread` messages, not the parallel replay. So the replay was serial and the `bc_pending` race in 8487ee8 is not my cause. - **Image-pool preallocation: yes.** The log of the session with the opaque blocks has `images from a pool of 128 MB blocks (memory type 0), 30 made at the start`, so 30 blocks (3.75 GB) were allocated up front, against the default of about 12 on this card (10% of VRAM). Your point about the deferred layers showing old BC blocks from another texture fits that; I cannot say whether the default would show them too. - **Duration.** I cannot tell you how long the blocks lasted: my two screenshots are 0.7 s apart and both show them, and I did not watch longer. The `N of 90 layers left` lines printed in that session are only the first 20 (the log stops printing after 20), so the countdown to the end is not in my log either; the 20 lines are all at the load (present ~2280), the blocks were on screen at present ~15960. What I can do next without a rebuild: a longer run with the split on at the default 16 and the preallocation at the default as well, to separate "split path" from "split path with a big preallocated pool". If I rebuild, I would add a log line when a deferred texture finishes, with its address. Tell me which of the two is more useful to you; I will report here either way.
metroid98 commented 2026-11-09 22:02:45 +00:00 (Migrated from github.com)

Thanks, that settles parallel replay. The gap you found (deferrals at present ~2280, blocks at ~15960) is the key question: did that array's continuation ever finish? Pushed f494015, which adds the line you suggested: vk: BC3 texture …: its last N deferred layers are in (K finished so far) when a texture's deferred layers are all uploaded, and … destroyed with deferred layers still to come when one is dropped. If your next run with the default 16 shows the blocks, three cases separate cleanly:

  • no "last … are in" line for the 1365x1365 x90 array: the continuation stalled;
  • it finished long before the blocks: the cause is elsewhere;
  • it was dropped: eviction removed it before it finished.

Running with the default pool size at the same time, as you planned, would separate the pool question as well. (AI-assisted via Claude Code on my behalf; not built here.)

Thanks, that settles parallel replay. The gap you found (deferrals at present ~2280, blocks at ~15960) is the key question: did that array's continuation ever finish? Pushed f494015, which adds the line you suggested: `vk: BC3 texture …: its last N deferred layers are in (K finished so far)` when a texture's deferred layers are all uploaded, and `… destroyed with deferred layers still to come` when one is dropped. If your next run with the default 16 shows the blocks, three cases separate cleanly: - no "last … are in" line for the 1365x1365 x90 array: the continuation stalled; - it finished long before the blocks: the cause is elsewhere; - it was dropped: eviction removed it before it finished. Running with the default pool size at the same time, as you planned, would separate the pool question as well. (AI-assisted via Claude Code on my behalf; not built here.)
ZurielAtr commented 2026-11-09 22:55:10 +00:00 (Migrated from github.com)

Thanks @metroid98 for carrying this, and @lucasmazzoni45-del for the careful runs. Reading the current head (f494015), I found two holes in the split path that would explain opaque blocks. Both are fixed in one commit on top of f494015: 6f76660 on ZurielAtr:fix/bc3-parts-fill.

  1. Deferred layers showed stale image memory. Until texture_bc_continue reached them, a new image's deferred layers held whatever its memory held before. With pooled image memory (VMA blocks, and more so with a large preallocated pool), that is other textures' old BC3 blocks: opaque black, purple, yellow and red squares with BC-block edges. My original comment ("a frame or two of a scene change") only covered how long, not what was shown. Now, when a new image defers layers, they are filled in the same recording with a VRAM-to-VRAM vkCmdCopyImage of the last layer encoded (every level). There is no decode or encode, so the long submission does not come back. A texture that was uploaded before keeps its old layers meanwhile.

  2. A failed continuation dropped its layers for good, and the new line called it finished. If upload_astc_gpu returns false inside texture_bc_continue (no staging arena, no scratch), nothing went back on bc_pending. So bc_pending.size() == before, and the log said "its last N deferred layers are in", while those layers kept the stale memory until the texture was made again. That would also fit blocks that do not move between screenshots 0.7 s apart. The entry now goes back on the list (up to 8 tries), "in" is logged only when it recorded, and giving up is logged as such.

tests/test_bc_parts.py covers both: fill_source / retry_continue, plus source checks that fail without either fix.

Tested on RX 7700S 8 GB, Windows 11, Adrenalin 26.10.1, v2.0.11 + this PR + the fix, default budget (16 M texels): one session of about 5.5 minutes in play, including the spot where I used to see blocks in the sky. Seven textures deferred layers (the two 1365x1365 x90 terrain arrays, twice each, plus three small arrays); all seven logged filled from layer 0 and then its last N deferred layers are in. None was could not be uploaded, there was no device lost, and no opaque blocks in the sky.

@metroid98, feel free to cherry-pick it onto this branch (git fetch https://github.com/ZurielAtr/Hookshot fix/bc3-parts-fill && git cherry-pick 6f76660).

AI-assisted (Claude Code) on my behalf.

Thanks @metroid98 for carrying this, and @lucasmazzoni45-del for the careful runs. Reading the current head (f494015), I found two holes in the split path that would explain opaque blocks. Both are fixed in one commit on top of f494015: [6f76660](https://github.com/ZurielAtr/Hookshot/commit/6f76660d60300fa5d18e4d31d049da6405195d38) on [ZurielAtr:fix/bc3-parts-fill](https://github.com/ZurielAtr/Hookshot/tree/fix/bc3-parts-fill). 1. **Deferred layers showed stale image memory.** Until `texture_bc_continue` reached them, a new image's deferred layers held whatever its memory held before. With pooled image memory (VMA blocks, and more so with a large preallocated pool), that is other textures' old BC3 blocks: opaque black, purple, yellow and red squares with BC-block edges. My original comment ("a frame or two of a scene change") only covered how long, not what was shown. Now, when a new image defers layers, they are filled in the same recording with a VRAM-to-VRAM `vkCmdCopyImage` of the last layer encoded (every level). There is no decode or encode, so the long submission does not come back. A texture that was uploaded before keeps its old layers meanwhile. 2. **A failed continuation dropped its layers for good, and the new line called it finished.** If `upload_astc_gpu` returns `false` inside `texture_bc_continue` (no staging arena, no scratch), nothing went back on `bc_pending`. So `bc_pending.size() == before`, and the log said "its last N deferred layers are in", while those layers kept the stale memory until the texture was made again. That would also fit blocks that do not move between screenshots 0.7 s apart. The entry now goes back on the list (up to 8 tries), "in" is logged only when it recorded, and giving up is logged as such. `tests/test_bc_parts.py` covers both: `fill_source` / `retry_continue`, plus source checks that fail without either fix. Tested on RX 7700S 8 GB, Windows 11, Adrenalin 26.10.1, v2.0.11 + this PR + the fix, default budget (16 M texels): one session of about 5.5 minutes in play, including the spot where I used to see blocks in the sky. Seven textures deferred layers (the two 1365x1365 x90 terrain arrays, twice each, plus three small arrays); all seven logged `filled from layer 0` and then `its last N deferred layers are in`. None was `could not be uploaded`, there was no device lost, and no opaque blocks in the sky. @metroid98, feel free to cherry-pick it onto this branch (`git fetch https://github.com/ZurielAtr/Hookshot fix/bc3-parts-fill && git cherry-pick 6f76660`). AI-assisted (Claude Code) on my behalf.
metroid98 commented 2026-11-09 23:03:38 +00:00 (Migrated from github.com)

Thanks @ZurielAtr, both holes are real. The second is in the log line I added: it would have called a failed continuation "in". I fast-forwarded this PR to your 6f76660, so it's now the head here, with your authorship kept. The fill is a VRAM copy inside the same recording, so it shouldn't bring back the long submission. @lucasmazzoni45-del, a run of this head with the default 16 would now be the real test: no opaque blocks at all, plus the new filled from layer and last … are in lines. Still a draft until then. (AI-assisted via Claude Code on my behalf; not built here.)

Thanks @ZurielAtr, both holes are real. The second is in the log line I added: it would have called a failed continuation "in". I fast-forwarded this PR to your 6f76660, so it's now the head here, with your authorship kept. The fill is a VRAM copy inside the same recording, so it shouldn't bring back the long submission. @lucasmazzoni45-del, a run of this head with the default 16 would now be the real test: no opaque blocks at all, plus the new `filled from layer` and `last … are in` lines. Still a draft until then. (AI-assisted via Claude Code on my behalf; not built here.)
lucasmazzoni45-del commented 2026-11-09 23:11:51 +00:00 (Migrated from github.com)

Thanks @ZurielAtr and @metroid98, both holes read right to me, and the first one describes what I saw (opaque black, purple, yellow and red squares with BC-block edges, not moving between two screenshots).

I will run the head you pushed (6f76660) tomorrow on the RX 7800 XT / Windows 11, with the defaults you asked for: the split at 16 and the image pool at its default size, no RX_VK_BC_PART_MTEXELS and no RX_VK_IMAGE_PREALLOC. I will go through Castle Town below the ruined castle (where I first saw the blocks), out to Hyrule Field and back, and report here whether any opaque blocks show up, plus the new filled from layer and last ... are in lines from the log.

I will also look at what it does to performance on this card: frame times and the replay submit / memory sync figures from the log, compared with a session of the same build with the split off. I will keep that apart from the blocks result, and I will say how long each session was so the numbers are not over-read.

Thanks @ZurielAtr and @metroid98, both holes read right to me, and the first one describes what I saw (opaque black, purple, yellow and red squares with BC-block edges, not moving between two screenshots). I will run the head you pushed (6f76660) tomorrow on the RX 7800 XT / Windows 11, with the defaults you asked for: the split at 16 and the image pool at its default size, no `RX_VK_BC_PART_MTEXELS` and no `RX_VK_IMAGE_PREALLOC`. I will go through Castle Town below the ruined castle (where I first saw the blocks), out to Hyrule Field and back, and report here whether any opaque blocks show up, plus the new `filled from layer` and `last ... are in` lines from the log. I will also look at what it does to performance on this card: frame times and the replay `submit` / `memory sync` figures from the log, compared with a session of the same build with the split off. I will keep that apart from the blocks result, and I will say how long each session was so the numbers are not over-read.
lucasmazzoni45-del commented 2026-11-09 23:33:54 +00:00 (Migrated from github.com)

Thanks @metroid98 and @ZurielAtr! Tomorrow I'll run the current head
(6f76660) with the default 16, both with my larger pool and with the
default pool size, and report whether the opaque blocks are gone and
whether the filled from layer / last … are in lines show up.

On Tue, Nov 10, 2026 12:04 AM, metroid98 @.***> wrote:

metroid98 left a comment (NotRexed/Hookshot#1130)
https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130

Thanks @ZurielAtr https://github.com/ZurielAtr, both holes are real.
The second is in the log line I added: it would have called a failed
continuation "in". I fast-forwarded this PR to your 6f76660
https://git.magicbean.dev/MagicBeanDev/Hookshot/commit/6f76660d60300fa5d18e4d31d049da6405195d38,
so it's now the head here, with your authorship kept. The fill is a VRAM
copy inside the same recording, so it shouldn't bring back the long
submission. @lucasmazzoni45-del https://github.com/lucasmazzoni45-del,
a run of this head with the default 16 would now be the real test: no
opaque blocks at all, plus the new filled from layer and last … are in
lines. Still a draft until then. (AI-assisted via Claude Code on my behalf;
not built here.)

—
Reply to this email directly, view it on GitHub
https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130?email_source=notifications&email_token=BXKPXORHNMTUF6NGEZVK2CL5YJEOHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMNZVGM4DGMRZGA42M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-6753832909,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/BXKPXOWS3MSGAJTXHBPBINL5YJEOHAVCNFSNUABGKJSXA33TNF2G64TZHMYTINBWHE3DENJSGA5US43TOVSTWNRSHA3TCMBVGQYDDILWAI
.
You are receiving this because you were mentioned.Message ID:
@.***>

Thanks @metroid98 and @ZurielAtr! Tomorrow I'll run the current head (6f76660) with the default 16, both with my larger pool and with the default pool size, and report whether the opaque blocks are gone and whether the `filled from layer` / `last … are in` lines show up. On Tue, Nov 10, 2026 12:04 AM, metroid98 ***@***.***> wrote: > *metroid98* left a comment (NotRexed/Hookshot#1130) > <https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130> > > Thanks @ZurielAtr <https://github.com/ZurielAtr>, both holes are real. > The second is in the log line I added: it would have called a failed > continuation "in". I fast-forwarded this PR to your 6f76660 > <https://git.magicbean.dev/MagicBeanDev/Hookshot/commit/6f76660d60300fa5d18e4d31d049da6405195d38>, > so it's now the head here, with your authorship kept. The fill is a VRAM > copy inside the same recording, so it shouldn't bring back the long > submission. @lucasmazzoni45-del <https://github.com/lucasmazzoni45-del>, > a run of this head with the default 16 would now be the real test: no > opaque blocks at all, plus the new filled from layer and last … are in > lines. Still a draft until then. (AI-assisted via Claude Code on my behalf; > not built here.) > > — > Reply to this email directly, view it on GitHub > <https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130?email_source=notifications&email_token=BXKPXORHNMTUF6NGEZVK2CL5YJEOHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMNZVGM4DGMRZGA42M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-6753832909>, > or unsubscribe > <https://github.com/notifications/unsubscribe-auth/BXKPXOWS3MSGAJTXHBPBINL5YJEOHAVCNFSNUABGKJSXA33TNF2G64TZHMYTINBWHE3DENJSGA5US43TOVSTWNRSHA3TCMBVGQYDDILWAI> > . > You are receiving this because you were mentioned.Message ID: > ***@***.***> >
lucasmazzoni45-del commented 2026-11-09 23:44:20 +00:00 (Migrated from github.com)

Small change of plans: I'm setting everything up for testing right now
instead of tomorrow. I'll run the current head (6f76660) with the default
16 and report back here with the log (opaque blocks or not, plus the
filled from layer / last … are in lines).

On Tue, Nov 10, 2026 12:04 AM, metroid98 @.***> wrote:

metroid98 left a comment (NotRexed/Hookshot#1130)
https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130

Thanks @ZurielAtr https://github.com/ZurielAtr, both holes are real.
The second is in the log line I added: it would have called a failed
continuation "in". I fast-forwarded this PR to your 6f76660
https://git.magicbean.dev/MagicBeanDev/Hookshot/commit/6f76660d60300fa5d18e4d31d049da6405195d38,
so it's now the head here, with your authorship kept. The fill is a VRAM
copy inside the same recording, so it shouldn't bring back the long
submission. @lucasmazzoni45-del https://github.com/lucasmazzoni45-del,
a run of this head with the default 16 would now be the real test: no
opaque blocks at all, plus the new filled from layer and last … are in
lines. Still a draft until then. (AI-assisted via Claude Code on my behalf;
not built here.)

—
Reply to this email directly, view it on GitHub
https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130?email_source=notifications&email_token=BXKPXORHNMTUF6NGEZVK2CL5YJEOHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMNZVGM4DGMRZGA42M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-6753832909,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/BXKPXOWS3MSGAJTXHBPBINL5YJEOHAVCNFSNUABGKJSXA33TNF2G64TZHMYTINBWHE3DENJSGA5US43TOVSTWNRSHA3TCMBVGQYDDILWAI
.
You are receiving this because you were mentioned.Message ID:
@.***>

Small change of plans: I'm setting everything up for testing right now instead of tomorrow. I'll run the current head (6f76660) with the default 16 and report back here with the log (opaque blocks or not, plus the `filled from layer` / `last … are in` lines). On Tue, Nov 10, 2026 12:04 AM, metroid98 ***@***.***> wrote: > *metroid98* left a comment (NotRexed/Hookshot#1130) > <https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130> > > Thanks @ZurielAtr <https://github.com/ZurielAtr>, both holes are real. > The second is in the log line I added: it would have called a failed > continuation "in". I fast-forwarded this PR to your 6f76660 > <https://git.magicbean.dev/MagicBeanDev/Hookshot/commit/6f76660d60300fa5d18e4d31d049da6405195d38>, > so it's now the head here, with your authorship kept. The fill is a VRAM > copy inside the same recording, so it shouldn't bring back the long > submission. @lucasmazzoni45-del <https://github.com/lucasmazzoni45-del>, > a run of this head with the default 16 would now be the real test: no > opaque blocks at all, plus the new filled from layer and last … are in > lines. Still a draft until then. (AI-assisted via Claude Code on my behalf; > not built here.) > > — > Reply to this email directly, view it on GitHub > <https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1130?email_source=notifications&email_token=BXKPXORHNMTUF6NGEZVK2CL5YJEOHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMNZVGM4DGMRZGA42M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-6753832909>, > or unsubscribe > <https://github.com/notifications/unsubscribe-auth/BXKPXOWS3MSGAJTXHBPBINL5YJEOHAVCNFSNUABGKJSXA33TNF2G64TZHMYTINBWHE3DENJSGA5US43TOVSTWNRSHA3TCMBVGQYDDILWAI> > . > You are receiving this because you were mentioned.Message ID: > ***@***.***> >
lucasmazzoni45-del commented 2026-11-09 23:46:35 +00:00 (Migrated from github.com)

Starting the test of 6f76660 now. Build: current main (0828863) with this head merged on top (one conflict, only in the test list in tests/run_all.py), no patches of mine, stock settings: the split at the default 16, no RX_VK_BC_PART_MTEXELS, no RX_VK_IMAGE_PREALLOC. RX 7800 XT / Windows 11.

The first start after the swap redoes the shaders and pipelines, so that session will not count for performance. After that I will walk Castle Town below the ruined castle, out to Hyrule Field and back, look for opaque blocks, and post the filled from layer / last … are in lines. Then a second session with my larger pool, and one with the split off for the frame-time comparison. Results here, with the length of each session.

Starting the test of 6f76660 now. Build: current main (0828863) with this head merged on top (one conflict, only in the test list in tests/run_all.py), no patches of mine, stock settings: the split at the default 16, no RX_VK_BC_PART_MTEXELS, no RX_VK_IMAGE_PREALLOC. RX 7800 XT / Windows 11. The first start after the swap redoes the shaders and pipelines, so that session will not count for performance. After that I will walk Castle Town below the ruined castle, out to Hyrule Field and back, look for opaque blocks, and post the `filled from layer` / `last … are in` lines. Then a second session with my larger pool, and one with the split off for the frame-time comparison. Results here, with the length of each session.
lucasmazzoni45-del commented 2026-11-10 00:33:18 +00:00 (Migrated from github.com)

Result of 6f76660 on RX 7800 XT / Windows 11: the split runs and the loading is fast; I cannot yet say the opaque blocks are gone for good.

Build and setup: current main (0828863) with this head merged (one conflict, only in the test list in tests/run_all.py), no other patches. RX 7800 XT 16 GB, Ryzen 7 5800X3D, 2560x1440 fullscreen, frame generation x2, frame pacing on, empty hookshot_env.txt (so the split is at the default 16, no RX_VK_BC_PART_MTEXELS, no RX_VK_IMAGE_PREALLOC). Two mods were active (a fix for 3 damaged textures and a UI mod). Played with a save: Ganon's Castle area as adult Link, Zora's River path, Zora's Domain (frozen) and back. About 27 minutes so far, one session, normal play and not a scripted route. Castle Town and Hyrule Field are not done yet.

What the log shows:

  • The new lines are there: 7 deferred layers filled from layer N until they are in, 7 its last N deferred layers are in (so every fill finished), and 21 N of 90 layers left for the next recordings. All of them are two BC3 1365x1365 x90 textures (the terrain tiles). One fill at the first load (about 0.5 min after the start), then 2 at about 6 minutes, 2 at about 17 minutes and 2 about half a minute later.
  • No device lost, no did not complete in time, no error. 60 fps for the game; after the first minute: mean 57.7 fps over 780 five-second samples, 63 of them under 50 fps, lowest 24.1.
  • Slow submits of 40 ms or more: 18 in all, 6 of 100 ms or more. Of these, one of 719.6 ms is shader compile (pipelines 707.5), the ones at the start are the boot, and one of 499.9 ms (draw 201, descriptors 136, texture lookups 128) comes right after the log line where two of these textures were filled from layer 0/1 at once. The later fills (about 17 min) have no slow submit of 40 ms or more. So at least once a fill coincides with a half-second hitch; I cannot say if the fill is the cause (the same second also has the first sight of new textures).

What I saw playing (my own words, no measurement):

  • Loading is quick; textures that stay flat-coloured while they load (an owl, for example) are much fewer than on my previous build, which had a bigger pool and the split off. Flat colour is still there for a moment on some.
  • I did not see black, purple, yellow or red opaque squares with BC-block edges in this session.
  • Not from this PR, I think: the blocky white glow over Ganon's Castle (#1004, cleared when I left and came back), and posterised textures in Zora's Domain. Both reported separately.

I will do Castle Town below the ruined castle and Hyrule Field next, and a session with the split off for the frame-time comparison, and post those here.

**Result of 6f76660 on RX 7800 XT / Windows 11: the split runs and the loading is fast; I cannot yet say the opaque blocks are gone for good.** **Build and setup:** current main (0828863) with this head merged (one conflict, only in the test list in `tests/run_all.py`), no other patches. RX 7800 XT 16 GB, Ryzen 7 5800X3D, 2560x1440 fullscreen, frame generation x2, frame pacing on, empty `hookshot_env.txt` (so the split is at the default 16, no `RX_VK_BC_PART_MTEXELS`, no `RX_VK_IMAGE_PREALLOC`). Two mods were active (a fix for 3 damaged textures and a UI mod). Played with a save: Ganon's Castle area as adult Link, Zora's River path, Zora's Domain (frozen) and back. About 27 minutes so far, one session, normal play and not a scripted route. Castle Town and Hyrule Field are not done yet. **What the log shows:** - The new lines are there: 7 `deferred layers filled from layer N until they are in`, 7 `its last N deferred layers are in` (so every fill finished), and 21 `N of 90 layers left for the next recordings`. All of them are two BC3 1365x1365 x90 textures (the terrain tiles). One fill at the first load (about 0.5 min after the start), then 2 at about 6 minutes, 2 at about 17 minutes and 2 about half a minute later. - No device lost, no `did not complete in time`, no error. 60 fps for the game; after the first minute: mean 57.7 fps over 780 five-second samples, 63 of them under 50 fps, lowest 24.1. - Slow submits of 40 ms or more: 18 in all, 6 of 100 ms or more. Of these, one of 719.6 ms is shader compile (`pipelines 707.5`), the ones at the start are the boot, and **one of 499.9 ms (draw 201, descriptors 136, texture lookups 128) comes right after the log line where two of these textures were filled from layer 0/1 at once**. The later fills (about 17 min) have no slow submit of 40 ms or more. So at least once a fill coincides with a half-second hitch; I cannot say if the fill is the cause (the same second also has the first sight of new textures). **What I saw playing (my own words, no measurement):** - Loading is quick; textures that stay flat-coloured while they load (an owl, for example) are much fewer than on my previous build, which had a bigger pool and the split off. Flat colour is still there for a moment on some. - I did not see black, purple, yellow or red opaque squares with BC-block edges in this session. - Not from this PR, I think: the blocky white glow over Ganon's Castle (#1004, cleared when I left and came back), and posterised textures in Zora's Domain. Both reported separately. I will do Castle Town below the ruined castle and Hyrule Field next, and a session with the split off for the frame-time comparison, and post those here.
lucasmazzoni45-del commented 2026-11-10 07:02:52 +00:00 (Migrated from github.com)

Correction to my run above: at Ganon's Castle I also saw, briefly, black
opaque blocks in the sky. This is separate from the white glow I mentioned
(#1004), which was a different thing. The black blocks went away after I
left the area and came back.

So this session was not fully clean: the blocks can still appear on head
6f76660 with the default split, but they did not persist after re-entering
the area. I don't have the exact time in the log, so I can't tie them to a
specific deferred fill yet.

Correction to my run above: at Ganon's Castle I also saw, briefly, black opaque blocks in the sky. This is separate from the white glow I mentioned (#1004), which was a different thing. The black blocks went away after I left the area and came back. So this session was not fully clean: the blocks can still appear on head 6f76660 with the default split, but they did not persist after re-entering the area. I don't have the exact time in the log, so I can't tie them to a specific deferred fill yet.
lucasmazzoni45-del commented 2026-11-10 08:08:18 +00:00 (Migrated from github.com)

Log lines from the 6f76660 session I reported above (RX 7800 XT, main 0828863 + this head, split at the default 16, empty hookshot_env.txt, about 27 minutes of play). Only the lines about the split path; I checked the whole log for could not be uploaded, destroyed with deferred, device lost and did not complete in time: none appear.

vk: BC3 texture 0x10a228a600 1365x1365 x90: its 87 deferred layers filled from layer 2 until they are in (1 so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: 87 of 90 layers left for the next recordings (1 so far)
  ... 3 layers a recording, 84, 81 ... (printed up to 30 left, the 20th line)
vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 3 deferred layers are in (1 finished so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: its 88 deferred layers filled from layer 1 until they are in (2 so far)
vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (3 so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 1 deferred layers are in (2 finished so far)
vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its last 1 deferred layers are in (3 finished so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (4 so far)
vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (5 so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 2 deferred layers are in (4 finished so far)
vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its last 2 deferred layers are in (5 finished so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (6 so far)
vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (7 so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: 74 of 90 layers left for the next recordings (200 so far)
vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 2 deferred layers are in (6 finished so far)
vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its last 2 deferred layers are in (7 finished so far)

What it shows: 7 fills, 7 "last N ... are in", so every fill finished, and only the two terrain arrays (0x10a228a600, 0x10a5b02c00) were ever deferred. Because the 20-line limit stops the "left" lines after the first fill, I cannot tell from the log how long the later fills took.

What it does not show: the black blocks in the sky at Ganon's Castle. I did not note the time, so I cannot say which fill they were near. If it is useful, next time I will write down the clock time when they appear, and can run with RX_VK_LOG_MADE/RX_VK_LOG_UPLOADS on. The full log is 6.4 MB; I can send the part around a given time on request.

Log lines from the 6f76660 session I reported above (RX 7800 XT, main 0828863 + this head, split at the default 16, empty `hookshot_env.txt`, about 27 minutes of play). Only the lines about the split path; I checked the whole log for `could not be uploaded`, `destroyed with deferred`, `device lost` and `did not complete in time`: none appear. ``` vk: BC3 texture 0x10a228a600 1365x1365 x90: its 87 deferred layers filled from layer 2 until they are in (1 so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: 87 of 90 layers left for the next recordings (1 so far) ... 3 layers a recording, 84, 81 ... (printed up to 30 left, the 20th line) vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 3 deferred layers are in (1 finished so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: its 88 deferred layers filled from layer 1 until they are in (2 so far) vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (3 so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 1 deferred layers are in (2 finished so far) vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its last 1 deferred layers are in (3 finished so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (4 so far) vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (5 so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 2 deferred layers are in (4 finished so far) vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its last 2 deferred layers are in (5 finished so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (6 so far) vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its 89 deferred layers filled from layer 0 until they are in (7 so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: 74 of 90 layers left for the next recordings (200 so far) vk: BC3 texture 0x10a228a600 1365x1365 x90: its last 2 deferred layers are in (6 finished so far) vk: BC3 texture 0x10a5b02c00 1365x1365 x90: its last 2 deferred layers are in (7 finished so far) ``` What it shows: 7 fills, 7 "last N ... are in", so every fill finished, and only the two terrain arrays (0x10a228a600, 0x10a5b02c00) were ever deferred. Because the 20-line limit stops the "left" lines after the first fill, I cannot tell from the log how long the later fills took. What it does not show: the black blocks in the sky at Ganon's Castle. I did not note the time, so I cannot say which fill they were near. If it is useful, next time I will write down the clock time when they appear, and can run with `RX_VK_LOG_MADE`/`RX_VK_LOG_UPLOADS` on. The full log is 6.4 MB; I can send the part around a given time on request.
lucasmazzoni45-del commented 2026-11-10 10:04:00 +00:00 (Migrated from github.com)

Two things from reading the code of the merged head (release/v2.0.12 + 6f76660) that may be worth a look for the opaque sky blocks. Neither is confirmed; I have no log or capture that ties them to the blocks.

1. Staging memory that is not cleared before the GPU decodes it (lead, unverified). In upload_astc_gpu (vk_texture.cpp ~883-885) the copy into the staging slot is skipped when at >= total and cut with n = min(tail, total - at). The rest of that layer's slot then keeps whatever the recycled staging arena held (staging(), ~382, does not clear it), and the GPU decodes it. That would give random coloured blocks. It only matters if a layer can reach those branches; I do not know whether it can for the sky. A cheap check: log when at >= total or n < tail; the fix would be to zero the tail.

2. A test that separates the deferred path from the rest: RX_VK_BC_PART_MTEXELS=0 turns the split off. If the blocks vanish with it, the deferral is involved; RX_VK_IMAGE_PREALLOC=0 and RX_VK_CAPTURE_KEEP_OLD=1 (my local pool and capture edits) rule those out. Earlier today on this card: the blocks were gone with the split off in Castle Town, but I saw them again briefly at Ganon's Castle with the default 16 on 6f76660, and could not tie them to a fill.

What I did check and found no defect in: the fill copy and its barriers, and bc_pending entries (destroy_later erases them, so no dangling Texture*). I did not review the race-related parts of vk_replay.cpp from this PR.

Also: this is the same sky I could not identify (the only deferred textures in my log are two 1365x1365 x90 BC3 arrays). If someone knows which texture the Castle Town / Ganon sky is, I can log that one.

Two things from reading the code of the merged head (`release/v2.0.12` + 6f76660) that may be worth a look for the opaque sky blocks. Neither is confirmed; I have no log or capture that ties them to the blocks. **1. Staging memory that is not cleared before the GPU decodes it (lead, unverified).** In `upload_astc_gpu` (`vk_texture.cpp` ~883-885) the copy into the staging slot is skipped when `at >= total` and cut with `n = min(tail, total - at)`. The rest of that layer's slot then keeps whatever the recycled staging arena held (`staging()`, ~382, does not clear it), and the GPU decodes it. That would give random coloured blocks. It only matters if a layer can reach those branches; I do not know whether it can for the sky. A cheap check: log when `at >= total` or `n < tail`; the fix would be to zero the tail. **2. A test that separates the deferred path from the rest:** `RX_VK_BC_PART_MTEXELS=0` turns the split off. If the blocks vanish with it, the deferral is involved; `RX_VK_IMAGE_PREALLOC=0` and `RX_VK_CAPTURE_KEEP_OLD=1` (my local pool and capture edits) rule those out. Earlier today on this card: the blocks were gone with the split off in Castle Town, but I saw them again briefly at Ganon's Castle with the default 16 on 6f76660, and could not tie them to a fill. What I did check and found no defect in: the fill copy and its barriers, and `bc_pending` entries (`destroy_later` erases them, so no dangling `Texture*`). I did not review the race-related parts of `vk_replay.cpp` from this PR. Also: this is the same sky I could not identify (the only deferred textures in my log are two 1365x1365 x90 BC3 arrays). If someone knows which texture the Castle Town / Ganon sky is, I can log that one.
lucasmazzoni45-del commented 2026-11-10 11:22:53 +00:00 (Migrated from github.com)

A small thing I hit when merging this PR's head (6f76660) into release/v2.0.12 (046e37f), in case it is not on the branch yet: tests/test_parallel_rb_refresh.py no longer compiles. The fixture tests/parallel_rb_refresh_test.cpp includes rb_texture.inc from the texture code, and the new thread_local uint64_t bc_part_texels (vk_texture.cpp ~854, used at ~911 and ~944) is not declared in the fixture. Adding one line beside the other thread-locals fixes it for me:

thread_local uint64_t bc_part_texels = 0;   // (vk_texture.cpp: the BC3 parts a recording holds; the fixture's texture refresh resets it)

With that, tests/run_all.py (llvm-mingw, Windows) gave 207 passed, 3 failed, 30 skipped; the 3 failures are toolchain ones on my side (test_fps_overlay_order, test_fpx_sticky could not find the C++ standard headers, test_precompile_compute_guard could not find windows.h), not this PR. I only ran it in that merge, not on the PR branch alone.

A small thing I hit when merging this PR's head (6f76660) into `release/v2.0.12` (046e37f), in case it is not on the branch yet: **`tests/test_parallel_rb_refresh.py` no longer compiles**. The fixture `tests/parallel_rb_refresh_test.cpp` includes `rb_texture.inc` from the texture code, and the new `thread_local uint64_t bc_part_texels` (`vk_texture.cpp` ~854, used at ~911 and ~944) is not declared in the fixture. Adding one line beside the other thread-locals fixes it for me: ```cpp thread_local uint64_t bc_part_texels = 0; // (vk_texture.cpp: the BC3 parts a recording holds; the fixture's texture refresh resets it) ``` With that, `tests/run_all.py` (llvm-mingw, Windows) gave 207 passed, 3 failed, 30 skipped; the 3 failures are toolchain ones on my side (`test_fps_overlay_order`, `test_fpx_sticky` could not find the C++ standard headers, `test_precompile_compute_guard` could not find `windows.h`), not this PR. I only ran it in that merge, not on the PR branch alone.
hckrman101 commented 2026-11-10 17:48:59 +00:00 (Migrated from github.com)

Heads-up: this conflicts with main now (a lot landed today). Could you merge main into the branch (or rebase) and resolve the conflicts? Thanks!

Heads-up: this conflicts with main now (a lot landed today). Could you merge main into the branch (or rebase) and resolve the conflicts? Thanks!
Joey-Magnus (Migrated from github.com) reviewed 2026-11-11 21:46:22 +00:00
Joey-Magnus (Migrated from github.com) left a comment

The Python source check failures are caused by this PR. tests/test_parallel_rb_refresh.py and tests/test_parallel_init_order.py cut texture code out of gpu/vk/vk_texture.cpp into their fixtures. The new bc_part_texels = 0; at vk_texture.cpp:1938 (and the use at :1950) now ends up in those fixtures without the thread_local declaration at :766, so both fail with "use of undeclared identifier 'bc_part_texels'". I reproduced test_parallel_rb_refresh.py locally on b4fed0c, and @lucasmazzoni45-del reported the same thing. The fixtures need the declaration added, or the reset moved out of the functions they cut. Loosening the text the tests match on would not be a fix.

The branch also conflicts with main again in vk_texture.cpp and tests/run_all.py. Main now discovers tests and reads each test's arguments from RUN_ALL_ARGS in the test file, so the run_all.py line can simply go.

The 16 M-texel split is the default on AMD, and the RX 7800 XT run on 6f76660 still showed black blocks at Ganon's Castle. I'd keep this in draft until a long, clean AMD run.

The Python source check failures are caused by this PR. tests/test_parallel_rb_refresh.py and tests/test_parallel_init_order.py cut texture code out of gpu/vk/vk_texture.cpp into their fixtures. The new `bc_part_texels = 0;` at vk_texture.cpp:1938 (and the use at :1950) now ends up in those fixtures without the `thread_local` declaration at :766, so both fail with "use of undeclared identifier 'bc_part_texels'". I reproduced test_parallel_rb_refresh.py locally on b4fed0c, and @lucasmazzoni45-del reported the same thing. The fixtures need the declaration added, or the reset moved out of the functions they cut. Loosening the text the tests match on would not be a fix. The branch also conflicts with main again in vk_texture.cpp and tests/run_all.py. Main now discovers tests and reads each test's arguments from RUN_ALL_ARGS in the test file, so the run_all.py line can simply go. The 16 M-texel split is the default on AMD, and the RX 7800 XT run on 6f76660 still showed black blocks at Ganon's Castle. I'd keep this in draft until a long, clean AMD run.
github-sync changed title from WIP: fix(vk): upload ASTC textures re-encoded as BC3 over several submissions (#900 rebased) to fix(vk): upload ASTC textures re-encoded as BC3 over several submissions (#900 rebased) 2026-11-12 15:49:25 +00:00
Owner

@lucasmazzoni45-del commented on GitHub · 2026-11-12 14:44 UTC · original

I rebased this onto current main on a branch in my fork: fix/pr1130-bc3-multisubmit. main is a single commit now, so the PR's net diff is applied as one commit.

  • Conflicts in vk_texture.cpp (kept main's astc_fail reasons plus the PR's astc_layer_size and run loop) and tests/run_all.py (main's version; RUN_ALL_ARGS added to test_bc_parts.py).
  • Fixtures tests/parallel_rb_refresh_test.cpp and tests/parallel_init_order_test.cpp now declare thread_local uint64_t bc_part_texels; the text the tests match on is unchanged. test_parallel_rb_refresh and test_parallel_init_order (with the Vulkan headers) pass.

Full suite on Windows (llvm-mingw, .NET 8): the failures are the same ones that fail on main here.

Still open: the AMD sky blocks at Ganon's Castle. A read of the code found no confirmed cause; a long AMD run at the default 16 M budget (with and without the large pool preallocation) is still needed.

🤖 Generated with Claude Code

> [@lucasmazzoni45-del](https://github.com/lucasmazzoni45-del) commented on GitHub · 2026-11-12 14:44 UTC · [original](https://github.com/NotRexed/Hookshot/pull/1130#issuecomment-6826768034) I rebased this onto current main on a branch in my fork: [fix/pr1130-bc3-multisubmit](https://github.com/lucasmazzoni45-del/Hookshot/tree/fix/pr1130-bc3-multisubmit). main is a single commit now, so the PR's net diff is applied as one commit. - Conflicts in `vk_texture.cpp` (kept main's `astc_fail` reasons plus the PR's `astc_layer_size` and run loop) and `tests/run_all.py` (main's version; `RUN_ALL_ARGS` added to `test_bc_parts.py`). - Fixtures `tests/parallel_rb_refresh_test.cpp` and `tests/parallel_init_order_test.cpp` now declare `thread_local uint64_t bc_part_texels`; the text the tests match on is unchanged. `test_parallel_rb_refresh` and `test_parallel_init_order` (with the Vulkan headers) pass. Full suite on Windows (llvm-mingw, .NET 8): the failures are the same ones that fail on main here. Still open: the AMD sky blocks at Ganon's Castle. A read of the code found no confirmed cause; a long AMD run at the default 16 M budget (with and without the large pool preallocation) is still needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- github-sync:c:6826768034 -->
Owner

@lucasmazzoni45-del commented on GitHub · 2026-11-12 14:46 UTC · original

Follow-up: while reading the deferred BC3 path I found a separate defect that could explain the colored sky blocks, though it is not confirmed as the cause. texture_touch (gpu/vk/vk_texture.cpp, the bc_retry_frame > frame_no early return and the end of the function after a failed upload) returns a BC3 texture whose image was never written, and nothing in vk_draw.cpp checks tex->uploaded, so a draw can sample uninitialised memory for up to 30 frames. The code comment says "not drawn as noise" but nothing enforced it. A fix (return nullptr like upload_defer does, and don't cache that null in texture_view_of, otherwise the retry never runs) is on top of this PR's branch in my fork: fix/bc3-unuploaded-not-sampled. Source-level test only (tests/test_bc_upload_retry.py); no GPU run. In the log with the blocks, the suspected texture was last used 482 presents before them and there is no "upload failed" line, so a run at Ganon's Castle with RX_VK_LOG_UPLOADS is still needed to tell.

🤖 Generated with Claude Code

> [@lucasmazzoni45-del](https://github.com/lucasmazzoni45-del) commented on GitHub · 2026-11-12 14:46 UTC · [original](https://github.com/NotRexed/Hookshot/pull/1130#issuecomment-6826800579) Follow-up: while reading the deferred BC3 path I found a separate defect that could explain the colored sky blocks, though it is not confirmed as the cause. `texture_touch` (`gpu/vk/vk_texture.cpp`, the `bc_retry_frame > frame_no` early return and the end of the function after a failed upload) returns a BC3 texture whose image was never written, and nothing in `vk_draw.cpp` checks `tex->uploaded`, so a draw can sample uninitialised memory for up to 30 frames. The code comment says "not drawn as noise" but nothing enforced it. A fix (return `nullptr` like `upload_defer` does, and don't cache that null in `texture_view_of`, otherwise the retry never runs) is on top of this PR's branch in my fork: [fix/bc3-unuploaded-not-sampled](https://github.com/lucasmazzoni45-del/Hookshot/tree/fix/bc3-unuploaded-not-sampled). Source-level test only (`tests/test_bc_upload_retry.py`); no GPU run. In the log with the blocks, the suspected texture was last used 482 presents before them and there is no "upload failed" line, so a run at Ganon's Castle with `RX_VK_LOG_UPLOADS` is still needed to tell. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- github-sync:c:6826800579 -->
Owner

@ZurielAtr commented on GitHub · 2026-11-12 14:59 UTC · original

One more fix for the split path, on ZurielAtr:fix/bc3-parts-fill: d1074fa "stage only the BC3 layers a recording takes", on top of 6f76660.

What was wrong. upload_astc_gpu copied every requested layer into staging and only then encoded the runs that fit the recording's budget. A continuation asks for all the layers still to come, so each one staged them all again: about 56 MB copied from guest memory to encode 2 or 3 of a 1365 x 1365 x 90 array's layers, about 1.3 GB per array over its recordings. On my RX 7700S (8 GB, Windows 11, Adrenalin 26.10.1, v2.0.11 + this PR + 6f76660, default 16 M budget), every reload of Hyrule Field's two terrain arrays cost 1.1-1.2 s, and one frame took 10.7 s (descriptors 9.4 s, staging arenas up to 32 x 64 MB).

The fix. The split is decided before staging (bc_parts::fit_layers): only the runs this recording takes are copied, and the rest goes on bc_pending with nothing staged. Per array that is about 56 MB of copies in all instead of about 1.3 GB. The fill of a new image's deferred layers and the retry of a failed continuation are unchanged, and the "left for the next recordings" line now also says how much was staged. tests/test_bc_parts checks that each layer is staged once, and that the split comes before the staging.

This may also be behind two things reported here, though I have not measured either: @Nitnek's ~1.2 s longer castle load on the RTX 3070 (since b7f5525 the budget is off on NVIDIA by default anyway), and the 500 ms submit @lucasmazzoni45-del saw right after two arrays were filled.

Applying it.

  • Onto this PR's head (b4fed0c): git fetch https://github.com/ZurielAtr/Hookshot fix/bc3-parts-fill && git cherry-pick d1074fa applies cleanly.
  • Onto @lucasmazzoni45-del's rebase on main (fix/pr1130-bc3-multisubmit): one conflict in vk_texture.cpp, at bc_scratch_layout. Keep main's astc_fail = "no memory for the BC3 scratch" and drop the old per-run layer_texels / run block, which fit_layers now replaces above the staging. After that it also applies cleanly onto fix/bc3-unuploaded-not-sampled.
  • I have not rebuilt or re-run the tests on either base. The fixture declaration of bc_part_texels that Lucas added is still needed.

About the sky blocks at Ganon's Castle. One data point that may save some searching. On the same machine (v2.0.11 + this PR + 6f76660), I saw purple and black blocks in the sky on Death Mountain Trail and took an F9 dump. The blocks first appear in the cloud draw, program 1a7482c0ec9991ea. It reads three 128 x 72 x 96 3D volumes that compute dispatches 1e2fcee33a0c7209 and 27ee9883e2a20323 write every frame (fog / volumetric light). That session's deferred BC3 layers had all logged "are in" early on, so that kind of sky block did not come from this PR. The same program also shows up in the log as a draw (program 1a7482c0ec9991ea) samples the colour target it writes (… read undefined where it writes), and it still does on v2.1.0. The dump kept only layer 0 of each volume, which was clean, while the sky samples far layers, so I could not go further. If the Ganon blocks are in that pass too, they are a separate bug.

AI-assisted (Claude Code) on my behalf.

> [@ZurielAtr](https://github.com/ZurielAtr) commented on GitHub · 2026-11-12 14:59 UTC · [original](https://github.com/NotRexed/Hookshot/pull/1130#issuecomment-6827131771) One more fix for the split path, on [ZurielAtr:fix/bc3-parts-fill](https://github.com/ZurielAtr/Hookshot/tree/fix/bc3-parts-fill): [d1074fa](https://github.com/ZurielAtr/Hookshot/commit/d1074fa903f7c1bfc03ab6ad7f378a5042e2cd70) "stage only the BC3 layers a recording takes", on top of 6f76660. **What was wrong.** `upload_astc_gpu` copied every requested layer into staging and only then encoded the runs that fit the recording's budget. A continuation asks for all the layers still to come, so each one staged them all again: about 56 MB copied from guest memory to encode 2 or 3 of a 1365 x 1365 x 90 array's layers, about 1.3 GB per array over its recordings. On my RX 7700S (8 GB, Windows 11, Adrenalin 26.10.1, v2.0.11 + this PR + 6f76660, default 16 M budget), every reload of Hyrule Field's two terrain arrays cost 1.1-1.2 s, and one frame took 10.7 s (descriptors 9.4 s, staging arenas up to 32 x 64 MB). **The fix.** The split is decided before staging (`bc_parts::fit_layers`): only the runs this recording takes are copied, and the rest goes on `bc_pending` with nothing staged. Per array that is about 56 MB of copies in all instead of about 1.3 GB. The fill of a new image's deferred layers and the retry of a failed continuation are unchanged, and the "left for the next recordings" line now also says how much was staged. `tests/test_bc_parts` checks that each layer is staged once, and that the split comes before the staging. This may also be behind two things reported here, though I have not measured either: @Nitnek's ~1.2 s longer castle load on the RTX 3070 (since b7f5525 the budget is off on NVIDIA by default anyway), and the 500 ms submit @lucasmazzoni45-del saw right after two arrays were filled. **Applying it.** - Onto this PR's head (b4fed0c): `git fetch https://github.com/ZurielAtr/Hookshot fix/bc3-parts-fill && git cherry-pick d1074fa` applies cleanly. - Onto @lucasmazzoni45-del's rebase on main ([fix/pr1130-bc3-multisubmit](https://github.com/lucasmazzoni45-del/Hookshot/tree/fix/pr1130-bc3-multisubmit)): one conflict in `vk_texture.cpp`, at `bc_scratch_layout`. Keep main's `astc_fail = "no memory for the BC3 scratch"` and drop the old per-run `layer_texels` / `run` block, which `fit_layers` now replaces above the staging. After that it also applies cleanly onto fix/bc3-unuploaded-not-sampled. - I have not rebuilt or re-run the tests on either base. The fixture declaration of `bc_part_texels` that Lucas added is still needed. **About the sky blocks at Ganon's Castle.** One data point that may save some searching. On the same machine (v2.0.11 + this PR + 6f76660), I saw purple and black blocks in the sky on Death Mountain Trail and took an F9 dump. The blocks first appear in the cloud draw, program `1a7482c0ec9991ea`. It reads three 128 x 72 x 96 3D volumes that compute dispatches `1e2fcee33a0c7209` and `27ee9883e2a20323` write every frame (fog / volumetric light). That session's deferred BC3 layers had all logged "are in" early on, so that kind of sky block did not come from this PR. The same program also shows up in the log as `a draw (program 1a7482c0ec9991ea) samples the colour target it writes (… read undefined where it writes)`, and it still does on v2.1.0. The dump kept only layer 0 of each volume, which was clean, while the sky samples far layers, so I could not go further. If the Ganon blocks are in that pass too, they are a separate bug. AI-assisted (Claude Code) on my behalf. <!-- github-sync:c:6827131771 -->
Commenting is not possible because the repository is archived.
No description provided.