Blocky light halos and checkerboard smoke go away when the few NEAREST samplers are made linear #1117
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
2 participants
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot#1117
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hookshot version
v2.0.7
What kind of problem
Graphics (missing, black or wrong-coloured things, lighting, flicker)
What happened
Expected: smooth halos and smooth haze.
What did not help
RX_VK_ASTC_RGBA8=1(#1006),RX_VK_WAIT_GPU=1. Skipping the three bloom passes (RX_VK_SKIP_PROG=b7914ae65792d0c8,ed4819446f84dcb4,1b464cb9d32aaae5) gives a black screen from the title.What fixed both
A diagnostic switch in
sampler_for(gpu/vk/vk_draw.cpp) that makes every non-compare sampler linear:With
RX_VK_FORCE_LINEAR=1the halos are smooth and the smoke has no checkerboard. I saw nothing else change.Which samplers
Only 9 samplers in a Kokiri session were NEAREST (VkFilter 0 = nearest, 1 = linear;
minfis NVN's min filter):Some combinations look odd (429: nearest magnification with trilinear minification), so either some samplers' filters are read wrongly, or some textures end up with the wrong sampler. I have not found which texture / program uses them yet. Forcing linear everywhere is a workaround, not a fix: a texture that really wants point sampling could suffer.
Possibly related: #1004 (blocky bloom, #606), #1006.
Where in the game
Kokiri Forest: lanterns, fairies, glowing flowers, and the haze
How often
Every time
Graphics card and driver version
RTX 5080 16 GB, NVIDIA 621.14
CPU, RAM and operating system
Ryzen 9 9900X3D, 64 GB, Windows 11 Pro
Changes from the defaults
Output resolution 3840x2160, Resolution 100 %.
hookshot_env.txt:
HOS_SCENE_NATIVE=1,HOS_FIX_RES=1, andRX_VK_FORCE_LINEAR=1(the test switch above, local build).Other software hooked into the game
No, nothing hooked in
hookshot_log.txt
hookshot_log.txt
hookshot_log.1.txt
hookshot_log.2.txt
hookshot_log.3.txt
hookshot_log.4.txt
Screenshots or video
Before (halos / smoke):
After
RX_VK_FORCE_LINEAR=1(same spots):<img width="794" heig
ht="963" alt="Image" src="https://github.com/user-attachments/assets/7f1ddbaf-fbbf-469e-9d92-cdaaef281868" />
Before you send it
Thanks, this is a clear and useful lead (9 NEAREST samplers, and RX_VK_FORCE_LINEAR=1 removes both artefacts). Linking this to #1006, where block squares and grid patterns are collected.
@NotRexed I can't set that variable partly because I'm on Windows and have an Nvidia graphics card. I don't know how to make it linear, you should put a setting that can be changed in the game in my opinion
Regression data from #606 (RX 9060 XT, Windows): the blocky light halos and black textures were gone on v2.0.6 and are back on v2.0.11 (log in #606).
Another data point for this one, on AMD and Windows: RX 7800 XT 16 GB, Ryzen 7 5800X3D, v2.0.11, 2560x1440, frame generation x2, default sampler settings (no
RX_VK_FORCE_LINEAR, I do not have that switch in my build).In the graveyard (Kakariko), in a strong light shaft, about 5 minutes after start, the bloom around the brightest part of the beam shows a grid of large translucent squares (roughly 85 x 60 px at 1280x720, repeated in two columns), mostly greyer than the glow around them and a few brighter. Two screenshots 0.6 s apart are the same, so it is not a flicker. It looks like the same family as the square halos and checkerboard in your report: a low-resolution glow drawn without filtering.
It is not the upscale network (
RX_VK_TAAU_KEYSis at its default, the stand-in) and not the BC3 split of #1130 (RX_VK_BC_PART_MTEXELS=0, no deferred layers in the log).I have not tried forcing the NEAREST samplers linear on this card yet. If someone adds the switch from your snippet (
RX_VK_FORCE_LINEAR) as an opt-in, I can run it on the 7800 XT and report whether the squares go away.Result on AMD / Windows for the switch in your report: with
RX_VK_FORCE_LINEAR=1the squares in the Kakariko graveyard light shaft are gone on an RX 7800 XT (v2.0.11, 2560x1440, frame generation x2). I added your snippet tosampler_foras an opt-in env switch in my own build, so it is off unless set; in the same save and the same spot the squares were gone with it on, and no other texture looked blurry in the few minutes played. Not a long test.The log lines the snippet prints (first 12), from one session:
Samplers 268 and 318 are exactly the two in your list with the same filters (268: mag linear, min NEAREST_MIPMAP_LINEAR; 318: mag nearest, min nearest, min filter 2), so the sampler ids seem to be stable between players. 435 is the same odd combination as your 429 (mag nearest, min linear with a linear mip filter,
minf5). That odd one supports your guess that some filters may be read wrongly, rather than the game really asking for point sampling.One lead I have not tested yet: the regression note above (clean on v2.0.6, back on v2.0.11) fits
9095043("cachesampler_for's samplers by id until a sampler registration changes"), which landed in v2.0.8 and has an off switch (RX_VK_SAMPLER_CACHE=0). If the cache can hand back a stale sampler for an id the game has re-registered, that would give "wrong sampler on some textures" without the filters being read wrongly. I will run the graveyard spot withRX_VK_SAMPLER_CACHE=0and the force-linear off, and post the result here.From #1499 (closed as a duplicate): the square light artifacts were not in v2.0.8 and appear from v2.0.9 on, which narrows the regression to the v2.0.8 → v2.0.9 changes.
Some checks on this, from a RX 7800 XT (Windows, v2.0.11 and a
release/v2.0.12build):git diff v2.0.8 v2.0.9, outside docs, tests and CI) isb784c68: the write-back diff and the presents' own queue made off by default (vk_main.cpp,vk_memory.cpp). So if the squares start at v2.0.9, that commit is the only candidate in the code. But I saw the squares (a translucent grid over a strong light shaft, Kakariko graveyard) on v2.0.11 withRX_VK_WB_DIFF=1, so I doubt the write-back diff is the cause by itself.nvn_api.h),host/nvn_native.creads min then mag in the right order, and the sampler id ishandle >> 20, consistent withnvnDeviceGetTextureHandle. I found no bit-field error that would produce the odd pairs (e.g. mag NEAREST with min LINEAR_MIPMAP_LINEAR).nvnSamplerPoolRegisterSampler(nvn_native.c~529) uses only the id, so a second sampler pool or an id registered again with other contents could leave the wrong sampler; andsampler_make's cache key hashes the struct's padding bytes (vk_draw.cpp~1777), which could create duplicates (harmless for the picture, but it hides real differences).RX_VK_FORCE_LINEAR=1exists inrelease/v2.0.12, andsampler N is nearest: ...is logged for the first 24 (vk_draw.cpp~1799). I will post those lines from a v2.0.12 log from this card, so the samplers' real values are on record.A test for AMD players who see the square / blocky halos around lights. Per #1499 they started between v2.0.8 and v2.0.9, and the only code change between those two was
b784c68, which turned off two things by default: the write-back diff and the presents' own queue. v2.0.11 turned the write-back diff back on and the halos are still there, so the present queue is the remaining suspect.On v2.0.12, add this line to
hookshot_env.txtbesideimage.bin(create the file if it doesn't exist):Then say whether the halos are gone, and attach
hookshot_log.txt. (It was turned off because it crashed some NVIDIA cards on newer drivers; on AMD it's only a test for now. Remove the line if anything goes wrong.)Result of the test, from an RX 7800 XT (Windows 11, Ryzen 7 5800X3D, 2560x1440, frame generation 2x with the v2.0.12 default, frame pacing on).
hookshot_env.txthad onlyRX_VK_PRESENT_QUEUE=1, and the log hasvk: presents on a queue of their own, of compute family 1.No square or blocky halos in either place I looked: the Sacred Forest Meadow (strong light shafts through the trees; the bloom around Navi is smooth) and the Kakariko graveyard, where I had seen the translucent grid over a light shaft on v2.0.11 about 5 minutes after the start. About 8 minutes of play so far in this session (about 30000 presents).
How much this proves: one session, two places, and the squares were intermittent for me before, so this is a lead for the present queue, not a confirmation. I will keep playing with it on and say here if they come back. I did not run the same session with the queue off, so there is no A/B from the same build.
This is not a stock build: v2.0.12 with PR #1130 merged at
6f76660, two local memory edits for AMD (image pool preallocation, larger capture buffer classes) and extra log lines. The picture-related code is the release's.The samplers that are NEAREST in this session (the first lines of the new log, as I promised above):
Sampler 268 (mag LINEAR, min 4 = NEAREST_MIPMAP_LINEAR) and 432 (mag NEAREST, min 5 = LINEAR_MIPMAP_LINEAR) are the odd combinations from the first post. I did not see squares in this session, so I cannot say which of these, if any, was involved before.
The full
hookshot_log.txtis 2 MB so far; I can attach it when the session is done if it helps.Thanks for testing! A correction to my earlier note: in v2.0.8 the separate present queue was only on by default with NVIDIA's driver on Windows, never on AMD. So turning it off in v2.0.9 changed nothing for AMD cards, and the queue can't be what started the halos. If
RX_VK_PRESENT_QUEUE=1really makes them go away on AMD, the more likely reading is that it changes timing enough to hide a race: a pass that reads a light or bloom target before the GPU has finished writing it, which AMD shows and NVIDIA doesn't. That's worth fixing at the source rather than by moving presents to another queue.So it would help to know:
RX_VK_PRESENT_QUEUE=1over a longer session and in a few places? (Squares were intermittent before.)RX_VK_BARRIER_EVERY_DRAW=1(much slower, a test only) also make them go away? If yes, it's a missing barrier, and the log can tell me where.Logs from both runs would be great.
Data for the race / read-while-write theory, from an RX 7800 XT (Windows 11, driver 0x8001a0, builds based on v2.0.12). The renderer already detects a draw that samples a target it is rendering to; it logs it, 12 lines at most, and goes on:
vk: a draw (program 5aae8ca508400194) samples the colour target it writes (64x64, read undefined where it writes)and... (program 3e753d8ad4012b7b) ... (130x130, read undefined where it writes).These lines are in all five play logs I have from this card (13 to 31 minutes each), so it happens in normal play, not rarely. I do not know yet whether these two programs belong to the bloom / light-shaft family named in this thread (1a7482c0ec9991ea, bbbc575ff0e57176, 1e2fcee33a0c7209, 27ee9883e2a20323, ed4819446f84dcb4, b7914ae65792d0c8, 1b464cb9d32aaae5); the cap of 12 lines hides how many other programs do it. A local build now lists every distinct program once (up to 64) with its target size, and I will post the list.
Why it may matter (reading of
draw_hazards,vk_draw.cpp~3759-3773, and the Vulkan rules; not tested on screen): the sampled image is in GENERAL layout inside the open render pass, which Vulkan does not define for a colour or depth attachment that is also sampled; AMD's compressed attachments (DCC/HTILE) could show that as blocks, while NVIDIA tolerates it. That would fit "AMD shows it, NVIDIA doesn't" and the grey squares, but it is a hypothesis;RX_VK_PRESENT_QUEUE=1hiding the squares on my card is also consistent with a timing-dependent read.For whoever works on a fix: this driver exposes
VK_EXT_attachment_feedback_loop_layout(featureattachmentFeedbackLoopLayout = true; the dynamic-state variant is not exposed) andVK_KHR_dynamic_rendering_local_read, so the legal way (a feedback-loop layout for those draws, or sampling a copy) is possible on RDNA3. I have not implemented it.Just adding my findings here, as requested.
I can confirm that the square-shaped lighting artifacts first appeared after updating from v2.0.8 to v2.0.9 and are still present in v2.0.11.
I tested disabling DLSS, Frame Generation, upscaling, and other graphical effects, but the issue persists even at native resolution.
System: RTX 5070 12 GB, Windows 11.
The artifacts affect multiple light sources throughout the game, especially Navi's glow. Everything was rendering correctly in v2.0.8.
Hope this helps narrow down the regression. Thanks for your work!
I'm trying out version 2.0.13, and this problem still exists before initialization.
System: RTX 3090ti 24 GB, Windows 11.
More on v2.0.14 from Discord: the grid in glows and fog, plus green square particles, on an RX 6700 XT and an RTX 5080;
RX_VK_ASTC_RGBA8=1doesn't change it. So it's not AMD-only and not the ASTC/BC3 texture path.Confirming this on v2.1.0, and that
RX_VK_FORCE_LINEAR=1fixes it for me.System
hookshot_options.iniin my game folder); output resolution 2048x1152 (the game's)What I saw
Inside Link's house in Kokiri Forest, large square pixelated blocks around the bright doorway and around Navi's glow. The rest of the frame was sharp.
With
RX_VK_FORCE_LINEAR=1inhookshot_env.txtThe blocks are gone in the same spot and I haven't noticed anything else looking different.
From the logs
sampler N is nearestlines. With the switch, each one is tagged(made linear: RX_VK_FORCE_LINEAR).a draw (program 3e753d8ad4012b7b) samples the colour target it writes, at 130x130 down to 1x1. These are still logged in the run where the squares are gone.The 9 nearest samplers (run without the switch)
Screenshots and logs (before = without the switch, after = with it)
Before:
After:
Logs:
I think the blocky halos in the logs attached here have one cause, and anyone who sees them can check it in his own
hookshot_log.txt: the textures and samplers the game registers before the renderer has started reach the Vulkan back end as all zeros. The game's sampler 258 is then a nearest sampler instead of a trilinear one.Look for these two lines (quoted from @dmajchrowski's log of the run with the blocks, v2.1.0):
Every field of both registrations is zero. In a log without them, the first
sampler anisotropyline readsthe game asks for 1 (min filter 5, ...)instead ofasks for 0 (min filter 0, ...): the same sampler, trilinear.The logs attached to this issue and to #1727, and one of mine (counted by a script with asserts, not by hand):
hookshot_log.txt,.1,.2,.4hookshot_log.3.txt(2160 presents)RX_VK_FORCE_LINEAR=1, blocks gonebdfe09cAll 13 attached logs say
rx: 123 texture and sampler calls made before the renderer started ..., given to it. Six have the zero sampler, and the same six have slots 0x102, 0x107 and 0x124 registered all zero; the other seven have neither. Where the nearest samplers are logged with their values (v2.0.12 on), the all-zero one is the only set of values that the logs with the fault have and the others lack: the odd-looking ones named above (268, and the one with nearest magnification and trilinear minification) are in the logs without the fault too. The id list in #1366's description (RTX 4080) has 258 in it as well.The cause, by reading main (
49f75dc8):host/rx_backend.ckeeps the registrations made beforerx_start(keep_early) and hands them to the renderer afterwards as pointers to its own copies on the heap (flush_early,forward).descriptor_okingpu/vk/vk_bank.cppdecides which memory a registration is copied from. A pointer outside the guest window is first given tohost->gpu_ptr(), and only then treated as host memory.hos_gpu_ptr(host/nvdrv.c) answers throughnvn_gpu_guest(host/nvn_native.c), for which every value from 16 MB (HOS_SYSTEM_BASE) to 512 GB (HOS_SPACE_END) is a guest address. A kept copy at such a host address is therefore read from the guest window's memory at that address: not the copy.P(i)), which the first check takes, andforwardpasses the kept copies.sampler_make(min and mag filter 0 are NVN's NEAREST); a texture slot registered as zeros has no image and is sampled as the dummy.Why it comes and goes: what I can show, and what I guess. It depends on the address the kept copies get. In @dmajchrowski's log with the blocks, the host thread logs
mem: 0x9873eec committed on first touch (nothing handed it out)betweenrx: renderer: Vulkan (hookshot_vk.dll)andrx: 123 ... given to it;rx_startdoes nothing between those two lines but hand the kept calls over, and 0x9873eec is inside the 16 MB to 512 GB range. That is one log. The other five logs with the zeros have no such line there, and I cannot show why the same PC gave a good run once (@wartechnology'shookshot_log.3.txt): my guess is the heap block's address, different from run to run. By the same reading a host pointer at or above 1 TB (VBASE) that falls inside a mapped page of a virtual pool (vmap_find; the pools get their addresses from 1 TB upward) would be misread the same way; no log shows that case.A fix and a test are on my fork: fix/vk-early-registration-copies.
descriptor_okno longer asksgpu_ptr; a pointer outside the guest window is the host's own memory ifVirtualQuerysays it is readable.tests/test_registration_host_copies.pyrunsdescriptor_okandnvn_gpu_guest, both cut from the source, with a kept copy at 0x9873eec: it fails on main and passes with the change. The pull request is #2289.Not done: I have not reproduced the blocks in a game. My machine is Linux (RTX 4090, NVIDIA 615.78.08); a run without a window starts the renderer before the game and keeps no calls (my log has no
rx: ... calls made before the renderer startedline), and the heap normally lies above 512 GB there. No Windows run, with or without the fix. I also cannot speak for the reports without a log (the RX 7800 XT's grid in light shafts, the RTX 5070, the RTX 3090 Ti), nor say that the checkerboard haze is the same fault: for @wartechnology the linear switch removed both, which fits the sampler, but that is his observation, not a log line.What would confirm or refute it:
An update on the cause I posted above: I can now show the picture of this issue on Linux, and that #2289 removes it.
I can't get a low heap address on Linux, so I made a local test switch that hands the early texture and sampler registrations to the renderer the way the Windows logs show it (as host copies at an address inside the range that is taken for guest memory). With it, main logs the same lines as @dmajchrowski's and @wartechnology's runs (
sampler 258 is nearest: min filter 0, ..., texture slots 0x102, 0x107, 0x124 registered as zeros), and the glow around Navi and the lanterns turns into blocks. With #2289's change and the same hand-over, the lines are gone and the glow is smooth.The table, the lantern picture and the details are in the comment on #2289.
What is still missing is a Windows run: the emulation shows what the zeros do and that the change stops them, not which addresses a Windows heap really gives. If one of you with the blocks can build #2289, the two log lines above should be gone, and the first
sampler anisotropyline should readthe game asks for 1 (min filter 5, ...).Thanks for the report. Reports of the same problem are now collected in #1004, which lists this one with your details and links back here, so one fix closes them together and the open list stays readable. Follow #1004 for the fix, and add new details there (or here). If this turns out to be a separate problem it will be reopened. Pull request #1366 works on this.
github-sync referenced this issue2026-11-12 06:22:54 +00:00
MY config
AMD Ryzen 7 5800X
RTX 3090
16go ddr4
the problem appears only when i'm loading a save
i don't have any other paterns it solve itself quite randomly but comes back
heres are the log of my session when i had the problem
hookshot_log.2.txt
hookshot_log.3.txt
hookshot_log.4.txt
for comparison some logs when i didn't have the problem
hookshot_log.1.txt
hookshot_log.txt