feat(vk): the upscalers' texture LOD bias at Auto, from the size drawn #1654
Closed
TwoToneEddy wants to merge 6 commits from
TwoToneEddy/upscale-lod-bias into main
pull from: TwoToneEddy/upscale-lod-bias
merge into: MagicBeanDev:main
MagicBeanDev:main
MagicBeanDev:github/pr/2893
MagicBeanDev:github/pr/2890
MagicBeanDev:github/pr/2887
MagicBeanDev:github/pr/2878
MagicBeanDev:github/pr/2875
MagicBeanDev:github/pr/2874
MagicBeanDev:github/pr/2873
MagicBeanDev:github/pr/2871
MagicBeanDev:github/pr/2756
MagicBeanDev:github/pr/2897
MagicBeanDev:github/pr/2896
MagicBeanDev:github/pr/2718
MagicBeanDev:github/pr/2842
MagicBeanDev:github/pr/2691
MagicBeanDev:github/pr/2895
MagicBeanDev:github/pr/2743
MagicBeanDev:github/pr/2765
MagicBeanDev:github/pr/2708
MagicBeanDev:github/pr/2732
MagicBeanDev:github/pr/2755
MagicBeanDev:github/pr/2817
MagicBeanDev:github/pr/2876
MagicBeanDev:release-please--branches--main
MagicBeanDev:release-please--branches--main--release-notes
MagicBeanDev:github/pr/2778
MagicBeanDev:github/pr/2888
MagicBeanDev:github/pr/2866
MagicBeanDev:github/pr/2877
MagicBeanDev:github/pr/2800
MagicBeanDev:github/pr/2829
MagicBeanDev:github/pr/2850
MagicBeanDev:github/pr/2889
MagicBeanDev:github/pr/2882
MagicBeanDev:github/pr/2860
MagicBeanDev:github/pr/2849
MagicBeanDev:github/pr/2886
MagicBeanDev:github/pr/2794
MagicBeanDev:github/pr/2840
MagicBeanDev:github/pr/2830
MagicBeanDev:github/pr/2834
MagicBeanDev:github/pr/2719
MagicBeanDev:github/pr/2742
MagicBeanDev:github/pr/2741
MagicBeanDev:github/pr/2820
MagicBeanDev:github/pr/2771
MagicBeanDev:github/pr/2859
MagicBeanDev:github/pr/2858
MagicBeanDev:github/pr/2823
MagicBeanDev:github/pr/2757
MagicBeanDev:github/pr/2769
MagicBeanDev:github/pr/2844
MagicBeanDev:github/pr/2843
MagicBeanDev:github/pr/2673
MagicBeanDev:github/pr/2855
MagicBeanDev:github/pr/2739
MagicBeanDev:github/pr/2807
MagicBeanDev:github/pr/2851
MagicBeanDev:github/pr/2789
MagicBeanDev:github/pr/2814
MagicBeanDev:github/pr/2818
MagicBeanDev:github/pr/2774
MagicBeanDev:github/pr/2772
MagicBeanDev:github/pr/2750
MagicBeanDev:github/pr/2786
MagicBeanDev:github/pr/2785
MagicBeanDev:github/pr/2782
MagicBeanDev:github/pr/2779
MagicBeanDev:github/pr/2775
MagicBeanDev:github/pr/2706
MagicBeanDev:github/pr/2766
MagicBeanDev:github/pr/2747
MagicBeanDev:github/pr/2759
MagicBeanDev:github/pr/2745
MagicBeanDev:github/pr/2740
MagicBeanDev:github/pr/2733
MagicBeanDev:github/pr/2725
MagicBeanDev:github/pr/2727
MagicBeanDev:github/pr/2728
MagicBeanDev:github/pr/2729
MagicBeanDev:github/pr/2721
MagicBeanDev:github/pr/2722
MagicBeanDev:github/pr/2715
MagicBeanDev:github/pr/2714
MagicBeanDev:github/pr/2707
MagicBeanDev:github/pr/2703
MagicBeanDev:github/pr/2705
MagicBeanDev:github/pr/2697
MagicBeanDev:github/pr/2679
MagicBeanDev:github/pr/2676
MagicBeanDev:github/pr/2669
MagicBeanDev:docs/what-hookshot-connects-to
MagicBeanDev:fix/hdr-encode-test
MagicBeanDev:fix/main-tests
MagicBeanDev:fix/play-cache-files
MagicBeanDev:perf/game-barrier-order
MagicBeanDev:feat/heap-lazy
MagicBeanDev:feat/texture-detail
MagicBeanDev:perf/astc-opaque-bc1
MagicBeanDev:fix/fs-dir-lock
MagicBeanDev:fix/framegen-native-kept
MagicBeanDev:fix/update-no-downgrade
MagicBeanDev:port/k10-gcn-f16-mirrors
MagicBeanDev:fix/framegen-mult-cap
MagicBeanDev:chore/release-as-2.1.1
MagicBeanDev:perf/pcache-load-switch
MagicBeanDev:fix/prepare-progress-log
MagicBeanDev:fix/update-closes-stale-game
MagicBeanDev:fix/hdr-scaled-sampled
MagicBeanDev:perf/first-start-preset
MagicBeanDev:perf/zero-upload
MagicBeanDev:fix/vcore-escape-2s
MagicBeanDev:test/fake-gh-atomic
MagicBeanDev:perf/batch-idle-flush
MagicBeanDev:test/finish-stub-a
MagicBeanDev:chore/record-2.1.0
MagicBeanDev:fix/main-red-tests
MagicBeanDev:fix/test-display-startup-driver-cache
MagicBeanDev:feat/mesh-shader-mode
MagicBeanDev:fix/menu-probes-at-startup
MagicBeanDev:fix/fps-counter-classic
MagicBeanDev:fix/test-log-batch-flake
MagicBeanDev:fix/narrow-screen-hud
MagicBeanDev:ci/prereleases
MagicBeanDev:release/v2.0.15
MagicBeanDev:hotfix/v2.0.15
MagicBeanDev:fix/present-ahead-replay
MagicBeanDev:release/v2.0.13
MagicBeanDev:fix/bracket-paths-2013
MagicBeanDev:fix/hdr-overlays-2013
MagicBeanDev:fix/fps-counter-scale-2013
MagicBeanDev:fix/stick-seen-at-rest
MagicBeanDev:hotfix/menu-fits-screen
MagicBeanDev:fix/f1-always-opens-menu
MagicBeanDev:fix/ini-keep-lines
MagicBeanDev:claude/cranky-pike-7cf247
MagicBeanDev:perf/texture-answer-flat
MagicBeanDev:fix/stamp-test-modules
MagicBeanDev:fix/appimage-fonts
MagicBeanDev:fix/display-awake
MagicBeanDev:release/v2.0.12
MagicBeanDev:fix/discord-windows
MagicBeanDev:rc/v2.0.12-tests
MagicBeanDev:fix/dlss-keep-feature
MagicBeanDev:rc/v2.0.12
MagicBeanDev:button-icons
No reviewers
Labels
Clear labels
accessibility
Barrier affecting people with disabilities
autorelease: pending
autorelease: tagged
bug
Something isn't working
dependencies
Pull requests that update a dependency file
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
github_actions
Pull requests that update GitHub Actions code
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
testing wanted
wontfix
This will not be worked on
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
Milestone
Clear milestone
No items
No milestone
Assignees
Clear assignees
No assignees
2 participants
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1654
Loading…
Reference in a new issue
No description provided.
Delete branch "TwoToneEddy/upscale-lod-bias"
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?
Main's upscaler texture LOD bias (#1898) is 0 at Auto, because the menu does not know the size the game's dynamic resolution draws. A scene the game shrank below its 3/4 under DLSS, FSR 3.1 or FSR 4 therefore lost its textures' detail there.
What this adds
upscale_lod_drew, called fromtemporal_upscaleandfsr3_upscale). At Auto the bias is main's samelog2(share / 0.75)of that measured share, in quarter mip levels (gpu/vk/upscale_lod_bias.h).samplers_changed()), after the step is stored.What it leaves as on main
upscale_lod_bias()'s rule: only the samplers the game biases below 0.RX_VK_UPSCALE_LOD_BIAS=0turns it off. There is no strength setting.The log's
vk: upscaler LOD bias at Auto:lines say what is measured.Checked
tests/test_upscale_lod_bias.py: the steps and the hold at an edge as C++ unit tests, and thatupscale_lod_drewis outsidevk_draw.cpp's anonymous namespace (it did not link before).vk_draw.cppbuilt to an object with g++:mkwvk::upscale_lod_drewis an exported symbol. The whole renderer was not linked here.🤖 Generated with Claude Code
Read through the diff and the surrounding code on main. The design holds together:
!gpu_written,levels > 1), never to compare samplers or ones without a mip filter, and only for the jittered B10G11R11 scene target at the size the upscaler last took. It is 0 for DLAA.sampler_make, with the unbiased key unchanged.sampler_forhas a separate biased table that checks the steps it was filled for.last_desc_lod_stepsis part ofsame_desc, so a draw with another bias rebuilds its descriptors, and this also holds withRX_VK_DESC_SLOTGEN. The compute path'sbuild_descriptorsis not affected because of the fragment-stage gate.Nits and housekeeping:
tests/test_upscale_lod_bias.pyis picked up byrun_all.pyautomatically but runs with its default--cxx g++. Other C++ tests list["--cxx", "{cxx}"]inARGS, which would also cover a Windows runner withoutg++on PATH.vk_draw.cpp, so it will break on harmless refactors. The C++ unit test is the useful part.fsr3_inputs::jitter_size. #1008's FSR 4 path doesn't set this, so it keeps the unbiased mips. That seems fine for now, but it is worth a follow-up if FSR 4 wants the same.Not run in-game as the description says, so I haven't seen how it looks. Approving on the code.
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!
Thanks for the review. Main is merged in, and each of your points is answered below.
Done. It is also ported to the TemporalEngine chain (#1008): the scale-to width now comes from
temporal_jitter_sizeaxis 3 invk_temporal.cpp, withfsr3_inputs::jitter_sizekept for FSR 3.1.Fixed. The test now declares
RUN_ALL_ARGS = ["--cxx", "{cxx}"]itself, since the centralARGStable is retired on main.Agreed. I've kept it in line with the other source-reading checks; the C++ unit test carries the logic.
Covered by the port. FSR 4 runs on the same chain as DLSS, so it takes the bias too (none for its Native AA, as for DLAA). Docs and readme are updated.
Checked
tests/test_upscale_lod_bias.pypasses, and the changed files pass a g++ syntax pass.Thanks for the merge and the answers. All four points from my last review are dealt with: the test now declares
RUN_ALL_ARGS = ["--cxx", "{cxx}"], the string-matching test is a fair call to keep, and the port to the TemporalEngine chain (temporal_jitter_sizeaxis 3, set besidejitter_w/jitter_hintemporal_upscale) is right. FSR 4 now gets the bias and Native AA gets none, becauserw == dwthere. The new code is fine as far as it goes.But main has moved under it again, and this time it's my fault: #1898 (merged at 19:53, after your 18:15 merge) landed an upscaler LOD bias of its own in
vk_draw.cpp(upscale_lod_bias(), added insampler_makeand part of the sampler key). That's why the PR is conflicting again (vk_draw.cpp,vk_temporal.*,vk_fsr3_inputs.*,readme.md,docs/development.md). Sorry about that. A plain merge would stack two biases, so the two need reconciling first:RX_VK_UPSCALE_LOD_BIASis just "0 = off". Here it's a 0..2 strength. If this PR's strength is kept, main's readme line needs updating too.lod_bias = -0.5for its 3/4 render (that's what the sampler log in #1898 showed). Main only addslog2(share / 0.75)on top of that, and only to the samplers the game biases below 0. This PR adds the fulllog2(render / picture)to every mipmapped scene texture, so those materials end up about 0.5 past the guides' number. DLSS Quality would be -1.0 total instead of about -0.58, and Performance -1.5 instead of -1.0. See inline.My suggestion: rebase onto main's
upscale_lod_bias(), and change it (or replace it) to use your measuredscene width / picture widthrelative to the game's 3/4, so that Auto is covered as well. Keep main's rule of biasing only the samplers the game biases, or say why the others (textures the game left at 0) should get it too. Then use one env var with one meaning. I'd also like @NotRexed's view on which shape he wants.CI hasn't run here (no checks reported while it conflicts). It's still not run in the game, which matters more for a sharpness change like this one.
p.lod_biasis already -0.5 for the game's world materials (its own bias for the 3/4 render), and the fulllog2(render/picture)goes on top of it here. With DLSS Quality that's about -1.0 in total, where the guides ask for about -0.58. On main,upscale_lod_bias()(#1898) only adds the part below 3/4 for that reason.No problem, and thanks for the detail. Main is merged in and I've reconciled the two the way you suggested.
upscale_lod_bias(), its rule (only the samplers the game biases below 0) andRX_VK_UPSCALE_LOD_BIAS=0are main's, unchanged; the 0..2 strength is gone.upscale_lod_drew, called fromtemporal_upscaleandfsr3_upscale), and at Auto the bias islog2(share / 0.75)of that, in quarter mip levels. Quarter levels because the size moves frame to frame and samplers are never destroyed.samplers_changed()is called when the step moves.Readme, docs row and tests are updated to match.
tests/run_all.pyfails only where main does on my machine. Still not run in-game. I'll update the PR title and description, which still describe the earlier, larger change.A heads-up before this gets merged: on today's main (
49f75dc8) the PR still merges without a text conflict, but the renderer no longer links. The build stops with:Cause: in
gpu/vk/vk_draw.cppon main, the anonymous namespace opened at line 72 now reaches past where this PR addsupscale_lod_drew()(around line 2333). The function becomes file-local, whilevk_temporal.cppandvk_fsr3.cppcall it throughvk_draw.h.Fix that works for me: close the anonymous namespace just around that one function. It still sees the file-local
upscale_lod_auto_stepsand the other names next to it.Checked: with that change the renderer links,
tests/test_upscale_lod_bias.pypasses, and the fulltests/run_all.pypasses. That was on main49f75dc8with this PR and about 30 other open PRs merged, on Linux with Clang through emsdk. Not run in game yet.🤖 Generated with Claude Code
Thanks for reconciling it with #1898. The points from my last review are dealt with:
upscale_lod_bias()with its rule (only the samplers the game biases below 0,log2(share / 0.75)) is used as is.RX_VK_UPSCALE_LOD_BIAS=0is off, as on main, and the 0..2 strength is gone.upscale_lod_drewintemporal_upscaleandfsr3_upscale). The quarter-level steps fromupscale_lod_bias.hare relative to the game's 3/4, and moving to a new step bumps the samplers' generation. That looks right to me, and so do the unit tests. Keeping the fixed Render resolutions exactly as on main is fine for this PR.Still open:
vk_draw.cppthe anonymous namespace that opens near the top of the file (line 68 here) only closes at line 3283, soupscale_lod_drewat 2193 is defined in it. Themkwvk::upscale_lod_drewthatvk_draw.hdeclares andvk_temporal.cpp/vk_fsr3.cppcall is then never defined. Main'supscale_lod_bias()sits in the same namespace, but only this file uses it. Closing the anonymous namespace around the one function, as Joey suggested, fixes it. A check intest_upscale_lod_bias.pywould also help, since none of the source-reading checks would catch this.vk_draw.cpp,vk_temporal.cpp,readme.mdanddocs/development.mdall moved), so it needs another merge of main. CI hasn't run beyond the title check because of that.One small thing, see inline: a share sitting on a quarter-step boundary could flip the step from frame to frame.
Still not run in the game, and @NotRexed hasn't said which shape he wants yet. Once it links and is merged up, I'm fine with it on the code.
This definition is inside the anonymous namespace that opens at line 68 and closes at 3283, so it's a file-local function, not the
mkwvk::upscale_lod_drewthatvk_draw.hdeclares.vk_temporal.cppandvk_fsr3.cppthen hit an unresolved symbol (Joey-Magnus's_ZN5mkwvk16upscale_lod_drewEjj).} // namespacebefore it andnamespace {after it fixes this.Nit / worth watching in the game: at Auto, if the dynamic resolution hovers where
lroundflips between two quarter steps, this bumps the samplers' generation every frame or two. That emptiessampler_for's tables and descriptor reuse each time. Thetoldlog stops after 16 lines, so you'd see it as a burst at start. If it happens, a little hysteresis (only move once the unrounded value is past the boundary by, say, an eighth of a level) would keep it steady.Thanks, that's resolved: nothing stacks now, and the Auto part is a clean addition on top of main's rule. One thing left, which is the link error (see my new review).
Sorry I didn't mean to close the PR. Hopefully it's all good now
The anonymous-namespace fix around
upscale_lod_drewis in, andtests/test_upscale_lod_bias.pypasses on this head. The Windows part 2/2 failure is on a base from before #2397 (thetest_native_astc_texture_countfix), so I don't think it's this PR.It conflicts again because #2441 (merged 14:27) moved the rule into
upscaler_rows::upscale_lod_bias_for(up, share, offset). For DLSS/DLAA it now covers Auto by assuming the game's 3/4 and addsRX_VK_DLSS_LOD_OFFSET(-1 by default). That covers part of what this PR adds. What's left is the measured share at Auto, which is worth keeping. I'd turn the measured steps into a share and pass it toupscale_lod_bias_forwhenresolution_scale() <= 0. Then DLSS getslog2(measured / 0.75) + offsetand FSR 3.1/4 getlog2(measured / 0.75), without a second Auto path insideupscale_lod_bias(). Note thatupscale_lod::steps()clamps at 0 from 3/4 up, which would drop DLSS's offset if used directly. The readme line should then describe the combined rule.This now conflicts with main in
docs/development.md,gpu/vk/vk_draw.cpp,readme.md. Could you merge main into the branch (or rebase) when you get a chance? I'll take another look once it's up to date.I think I'll leave it now, I've synced my fork and merge main so many times now and I see no indication this will ever be merged