aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-01 21:42:54 -0500
committerDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-01 21:54:48 -0500
commitd125cfb41c0b78b0f4880fac20fab65c913d97e3 (patch)
tree3080f9c07e3ef13e8002010e6bb9478becfda0fa /src
parentc08b5efbaa4a7a2da78ca4509bec823ad38d5223 (diff)
kepler_compute: stand in for Fortune's Weave's DLSS with an upscale
Every 3D frame of Fire Emblem: Fortune's Weave goes through its DLSS network, which the HMMA lowering cannot run, so its 3D scenes stayed black. The stand-in written for title 4 (handles at cbuf0+0x90/0xa0) never matched it. The network's last pass reads the input colour through cbuf0+0x328 and writes the output through cbuf0+0x348; when title 4's pair does not fit, blit those instead. Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting) Signed-off-by: Duck912 <350528965+Duck912@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/kepler_compute.cpp21
1 files changed, 15 insertions, 6 deletions
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index ab2ba10162..233304d273 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -590,7 +590,9 @@ 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
+// TLD/SUST operands). Fire Emblem: Fortune's Weave's DLSS network ends with a pass that reads the
+// input colour through cbuf0+0x328 and writes the DLSS output through cbuf0+0x348 (B10G11R11; 720p
+// to 1440p docked). Blit one to the other with bilinear filtering when both are plain 2D images
// of the same format and the output is larger.
bool KeplerCompute::UpscaleInsteadOfNativeProgram() {
const auto& cbuf = launch_description.const_buffer_config[0];
@@ -600,11 +602,18 @@ 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())
- return false;
+ const auto usable = [](const std::optional<Texture::TICEntry>& input,
+ const std::optional<Texture::TICEntry>& output) {
+ return input && output && input->format == output->format && input->Address() != 0 &&
+ output->Address() != 0 && output->Width() > input->Width() && input->IsBlockLinear() &&
+ output->IsBlockLinear();
+ };
+ auto input = image(0x90), output = image(0xa0);
+ if (!usable(input, output)) {
+ input = image(0x328);
+ output = image(0x348);
+ if (!usable(input, output)) return false;
+ }
using RTFormat = Tegra::RenderTargetFormat;
RTFormat format{};
switch (input->format) {