aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/engines/kepler_compute.cpp
diff options
context:
space:
mode:
authorDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-02 18:56:59 -0500
committerDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-02 18:56:59 -0500
commit9acd36eb9a291e0631346f5b17d69d0e8eb26cc5 (patch)
tree5142f9867928a2e7f07a6b6b79ca00fa5f900425 /src/video_core/engines/kepler_compute.cpp
parent11cebf56014a5015db28179a8acc81cad0caf641 (diff)
parent2d81fd5072c060737c18ed4cfc46a04fb8cbb94c (diff)
Merge remote-tracking branch 'origin/nx2' into fe-fsr31
# Conflicts: # src/video_core/renderer_vulkan/blit_image.cpp # src/video_core/renderer_vulkan/blit_image.h
Diffstat (limited to 'src/video_core/engines/kepler_compute.cpp')
-rw-r--r--src/video_core/engines/kepler_compute.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp
index 2d35b603ae..be6a1d5eac 100644
--- a/src/video_core/engines/kepler_compute.cpp
+++ b/src/video_core/engines/kepler_compute.cpp
@@ -694,8 +694,32 @@ bool KeplerCompute::UpscaleInsteadOfNativeProgram() {
result.addr_lower = static_cast<u32>(tic.Address());
return result;
};
+ // Title 4's program ends by decoding its result from sRGB to linear (the 0.04045 threshold
+ // and the 2.4 exponent as half-precision immediates of HSETP2 and HMUL2). The copy of its
+ // sRGB input left the frame gamma-encoded twice, washed out: decode in the copy when the
+ // program does.
+ static std::unordered_map<GPUVAddr, bool> decodes_srgb;
+ const GPUVAddr program = regs.code_loc.Address();
+ const auto [known, inserted] = decodes_srgb.try_emplace(program, false);
+ if (inserted) {
+ bool threshold = false, exponent = false;
+ std::array<u32, 0x400> block{};
+ for (u64 offset = 0; offset < 0x20000 && !(threshold && exponent); offset += sizeof(block)) {
+ if (!memory_manager.IsFullyMappedRange(program + offset, sizeof(block))) break;
+ memory_manager.ReadBlock(program + offset, block.data(), sizeof(block));
+ for (size_t word = 0; word < block.size(); word += 4) {
+ const u32 opcode = block[word] & 0xfff;
+ threshold |= opcode == 0x434 && block[word + 1] == 0x292d292d;
+ exponent |= opcode == 0x832 && block[word + 1] == 0x40cc40cc;
+ }
+ }
+ known->second = threshold && exponent;
+ LOG_INFO(HW_GPU, "Upscale fallback for program {:#x}: {}", program,
+ known->second ? "decodes sRGB like the program" : "plain copy");
+ }
const Fermi2D::Config config{
- .operation = Fermi2D::Operation::SrcCopy,
+ .operation = known->second ? Fermi2D::Operation::SrcCopySrgbToLinear
+ : Fermi2D::Operation::SrcCopy,
.filter = Fermi2D::Filter::Bilinear,
.must_accelerate = true,
.dst_x0 = 0,