aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/shader_environment.cpp
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 02:57:31 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 02:57:31 -0400
commitf7be55dbf1a313382a28bca067960a0fae95227f (patch)
treee1848e19ce40078d1b4ea5a8178ab86b6681d473 /src/video_core/shader_environment.cpp
parent3e48eedecf91f8f8d0917f8f78ce26a3d0482e5c (diff)
nx2: title 4's intro cutscene renders correctly
Native shader capture counted CALL.REL.NOINC as a function call, so a program using it waited for a RET after its EXIT and read on into the following shaders until a garbage branch target made it fail. NOINC calls push no return address (the compiler uses them as jumps; the lowering already treats them so): count them as forward branches. That shader builds title 4's 3D colour-grading LUT once per scene; with it rejected the LUT stayed empty and the tonemap turned every frame black. The intro cutscene now renders lit and graded, with subtitles, through the bilinear stand-in for the tensor-core upscaler. Also: rejected captures dump to EDEN_NX2_SHADER_DUMP as rejected-<addr>.bin and report the offending instruction.
Diffstat (limited to 'src/video_core/shader_environment.cpp')
-rw-r--r--src/video_core/shader_environment.cpp15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index fc2a26a568..5a14211073 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -338,8 +338,19 @@ void GenericEnvironment::InitializeNativeCode(u32 source_header_size) {
auto& instruction = native.emplace_back();
gpu_memory->ReadBlock(address, &instruction, sizeof(instruction));
const auto status = capture.Observe(instruction, index);
- if (status == Shader::Ampere::ProgramCaptureState::Result::InvalidTarget)
- throw Shader::RuntimeError("Native shader branch outside capture bounds");
+ if (status == Shader::Ampere::ProgramCaptureState::Result::InvalidTarget) {
+ if (const char* dir = std::getenv("EDEN_NX2_SHADER_DUMP")) {
+ const auto path = fmt::format("{}/rejected-{:x}.bin", dir, program_base + native_header_size);
+ if (std::FILE* file = std::fopen(path.c_str(), "wb")) {
+ std::fwrite(native.data(), sizeof(Instruction), std::min<size_t>(native.size(), 4096), file);
+ std::fclose(file);
+ }
+ }
+ throw Shader::RuntimeError("Native shader branch outside capture bounds at {:#x} +{:#x} [{:08x} {:08x} {:08x} {:08x}]",
+ program_base + native_header_size, index * 16,
+ instruction.words[0], instruction.words[1],
+ instruction.words[2], instruction.words[3]);
+ }
if (status == Shader::Ampere::ProgramCaptureState::Result::Complete) break;
}
auto lowered = Shader::Ampere::LowerToMaxwell(native);