diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-11-01 13:26:14 -0500 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-11-01 13:26:14 -0500 |
| commit | 12ea6f5d3da3adf642799600d0d000cfb47e1854 (patch) | |
| tree | cc7f595c102e9e9c6b31cb5cfc802d28ff95dc1d /src/video_core | |
| parent | b91817655ac7e72ae871ff668cea49da8082035e (diff) | |
| parent | 076b390110b6929400ff135fc59ca800164c9d41 (diff) | |
Merge remote-tracking branch 'origin/fix/nx2-upscale-pair-search' into test/linux-all-prs
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/kepler_compute.cpp | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index ab2ba10162..0377250fc1 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp @@ -590,8 +590,10 @@ std::atomic<u32> g_nx2_trace_draws_after_upscale{}; // Title 4's upscaler reads the tonemapped frame through the texture handle at cbuf0+0x90 and // writes the output resolution image through the surface handle at cbuf0+0xa0 (from its -// TLD/SUST operands). Blit one to the other with bilinear filtering when both are plain 2D images -// of the same format and the output is larger. +// TLD/SUST operands); Kirby Air Riders' reads a 2048x1152 image at cbuf0+0x80 and writes a +// 2560x1440 one at +0x90. Blit one to the other with bilinear filtering when both are plain 2D +// images of the same format and the output is larger: title 4's slots first, else the first two +// handles in cbuf0+0x80..0x11c that form such a pair. bool KeplerCompute::UpscaleInsteadOfNativeProgram() { const auto& cbuf = launch_description.const_buffer_config[0]; const GPUVAddr cbuf_address = (GPUVAddr{cbuf.address_high} << 32) | cbuf.address_low; @@ -600,10 +602,31 @@ bool KeplerCompute::UpscaleInsteadOfNativeProgram() { if (tic_index > regs.tic.limit) return std::nullopt; return GetTICEntry(tic_index); }; - const auto input = image(0x90), output = image(0xa0); - if (!input || !output || input->format != output->format || input->Address() == 0 || - output->Address() == 0 || output->Width() <= input->Width() || !input->IsBlockLinear() || - !output->IsBlockLinear()) + const auto upscale_pair = [](const std::optional<Texture::TICEntry>& from, + const std::optional<Texture::TICEntry>& to) { + return from && to && from->format == to->format && from->Address() != 0 && + to->Address() != 0 && to->Width() > from->Width() && from->IsBlockLinear() && + to->IsBlockLinear(); + }; + std::optional<Texture::TICEntry> input = image(0x90), output = image(0xa0); + if (!upscale_pair(input, output)) { + input.reset(); + output.reset(); + for (u32 first = 0x80; first < 0x120 && !input; first += 4) { + const auto from = memory_manager.Read<u32>(cbuf_address + first) != 0 ? image(first) + : std::nullopt; + for (u32 second = first + 4; from && second < 0x120; second += 4) { + if (memory_manager.Read<u32>(cbuf_address + second) == 0) continue; + const auto to = image(second); + if (upscale_pair(from, to)) { + input = from; + output = to; + break; + } + } + } + } + if (!input || !output) return false; using RTFormat = Tegra::RenderTargetFormat; RTFormat format{}; |
