Commit Graph

12 Commits

Author SHA1 Message Date
chrg6
745d48bc8c Free released recording copies outside their lock, skip the yield's lock and scans when nobody waits for a core, and wait instead of spinning before a paced frame.
Found by profiling a play session and reading the kernel and the command recording:
- nvn_api_cmd.c: a released recording copy had its pins uncounted (a walk over every op) and was freed while copy_lock was held exclusively; the main-loop thread waited for that lock 2.8% of its time. The copies are now chained under the lock and freed after it. The walks over a recording's records test a mask of the five op kinds that name pins before calling op_pins.
- kernel.c: SleepThread(0) took the kernel lock and computed the caller's inherited priority, a scan over every blocked thread, also when no thread waited for a core, which is nearly always. It now yields at once then. A wait without a timeout no longer reads the clock.
- nvn_api_obj.c sleep_until: the wait for a paced frame's slot slept coarsely and left the last 1 to 2 ms to a yield loop; the high-resolution wait now takes all but its own margin.
- input.c: the keyboard scan (a system call per key) is reused for reads within a millisecond.
- nvn_api_core.c: the read-lock observer's commit-point address is 1.2.1's and is now only compared there.
- kernel_probe.c: the probe expected three virtual cores and wait type 3 to be refused; the kernel has six cores and implements the 64-bit wait. It now checks both as they are, counts a core number past the cores as a clash without unbalancing core 0, and --probe-kernel passes again.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
(cherry picked from commit a3dbd63878d7d6de096ceb4c25988192b4bce738)
2026-11-09 20:48:10 -05:00
chrg6
ac5c196f3a Pace DLSS Frame Generation with Reflex from the frame's start, so it no longer halves the game's frame rate.
Reflex's markers sat at the host present with frame numbers unlike the frame's tags, slReflexSleep was never called, and the low-latency mode was set before any swapchain existed, so it never applied. GfxBackend.frame_start, called from nvnWindowAcquireTexture, now sets the simulation and submit-start markers after Reflex's sleep (skipped once nothing was presented for 200 ms); submit end is set when the frame's submissions went out; the mode is set again after each swapchain (NX2NAVI_REFLEX: 1 on, 0 off, 2 boost); frames are numbered by the game's presents; and the fps counter counts what was shown. NX2SL_VERSION is 3, so nx2navi_dlssg.dll must be rebuilt. From a tester's fixes: 42-45 fps game, 84-90 on screen (was 24).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 15:51:48 -05:00
chrg6
8647f19370 Check that a texture's packaged data fits its memory pool before copying it in.
nvnTextureInitialize copied the layout's size of packaged data to the pool's memory at the texture's offset without
checking either against the pool: a descriptor larger than its pool wrote past the pool's storage. It now stops
with the sizes instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 15:51:48 -05:00
chrg6
edce57ce5d Render DLSS's quality modes at their own scale by fixing the game's dynamic resolution.
The game sizes its scene each frame from a GPU-time controller. The new patch set res_fixed takes the controller's
fixed path and reads the scale from the patch page, so DLSS Quality, Balanced, Performance and Ultra Performance
render at 67, 58, 50 and 33 percent of the picture and DLAA at all of it. The set goes on once the controller has run
for a few frames, and the menu's Upscaling choice lists the modes and switches them live.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 10:59:59 -05:00
chrg6
99de7b943f Give each file of copied code one license line.
Each file that contains copied code names its copyright holder and license and points at THIRD_PARTY_NOTICES.md; zlib code keeps its full notice and the mark that it was altered. Comments and probe text only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 05:04:40 -05:00
chrg6
1b39aabd37 Describe what the code does in comments and docs.
Comments say what the code does and why, docs/maxwell.md keeps the Maxwell facts, and fetch_refs.sh clones only the checkout the build reads. Code is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 05:04:40 -05:00
chrg6
18b9ef3cd0 Log who sizes 16:9 textures with NX2NAVI_LOG_RT_SIZES.
A diagnosis for native ultrawide: each nvnTextureBuilderSetSize2D of a 16:9 size of at least 320 wide logs its
caller and the caller's caller (up to 200 lines).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 05:04:39 -05:00
chrg6
4943b50ff2 Unlock the frame rate, shorten cold starts, and describe the Ocarina build in the docs.
Ocarina steps its game by the clock (the same frame-numbered walk covers half the distance at 120 fps), so in a build
without the fps60 and realtime patch sets the pacer holds frames to the frame limit alone: any rate from 30 to 1000,
the monitor's rate, or unlimited (164 fps average in Kokiri Forest). The menu always shows the row, with 165, 240 and
Unlimited added. NX2NAVI_PACE_HZ sets the pacer's rate for tests.

A compute pipeline is compiled outside the pipeline lock, and one compile serves the replay and the boot prebuild
alike; the prebuild uses half the CPUs. The guest waits at most NX2NAVI_PREWARM_WAIT_MS (3000) for the boot prewarm,
which then goes on in the background (a cold start waited 9.8 s). NX2NAVI_TEST_PAD_AT attaches the test gamepad late
and presses it, to test a controller switched on in play.

README, docs/architecture.md, docs/controls.md and AGENTS.md describe the Ocarina build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 05:04:39 -05:00
chrg6
eed3e6b786 Decode the upscaler stand-in's picture with a square, emit SURED with its real opcode and keep the translator's warnings.
The post pass stores the square root of each channel, so the stand-in for Ocarina's untranslatable upscaler now
filters those values and squares them in its compute pass (shaders/fallback_tonemap.spvasm, vk_tonemap.c) instead of
decoding them with the sRGB curve, which darkened mid-tones and lifted the darkest values; the pass is compiled in again,
its round-24 device loss having been the push descriptor call outside the recorder. NX2NAVI_FALLBACK_EXPOSURE is gone.
AmpereLowering emitted SURED as 0xeb48, which matches no Maxwell instruction, so the translator skipped every image
reduction; with 0xeb58 the edge AA's blend-weight pass writes its image. The translator's own warnings go to res.json
notes, and shader dumps are named by program serial so they match the frame dumps' program numbers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 05:04:39 -05:00
chrg6
618b9ba4e5 Fix Ocarina's white dialogue frames, the fountain floor speckle and the button prompt text
The texture pool descriptors are now a ring of sets, one per submission, brought up to date from a change log, and the first submission of each frame waits for its GPU work before the game goes on: the GPU ran late and part of a frame read data of the next one, and distant characters drew NaN that bloom spread over the frame. The window acquire also waits for the image's previous frame. Function locals start at zero unless DLAA is on, which removes the per-warp light tiles on the Great Fairy Fountain floor and Link's dark, speckled look. Texture slots follow only live entries of their own target, so the volumetric fog gets its 3D volume. The pool refresh walks only the slots that changed.

The translator implements PRMT (patch 0021), which it only logged before; the button prompts render again. HFMA2.RELU no longer depends on it, HMMA.F16 rounds once and HMMA.F32 is lowered, checked against GPU vectors with a new Maxwell warp emulator.

The frame dump gains a re-arming white-frame trigger, a trigger on a depth target's first pass, NaN pixels in magenta, image handles and view targets, and depth copies of sampled depth textures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 05:04:39 -05:00
chrg6
77d0c0b84e Port Ocarina of Time (Switch 2) to the recomp host
The NVN2 front end and the SM86 to Maxwell shader lowering (tools/xlate/AmpereLowering.cs, mesh and task stages,
bindless texture pools, BRX jump tables, the NVN2 compute c0 layout) with four translator patches (0017-0020) bring the
opening of the game to 58-60 fps on the Vulkan renderer.

This round fixes the haze: SM86 IPA is lowered as a plain Maxwell IPA.PASS (texture coordinates were corrected for
perspective twice); LDSM, TXD, both F2IP byte forms, HMMA, MOVM and HFMA2.RELU are lowered and spill mode has eight
uniform register groups; conditional rendering keeps the newest counter report per address and treats a report as
pending until its value is in guest memory, so occlusion tests and the depth clears around the depth copy behave; and
the upscaler stand-in decodes the post pass's sRGB picture before writing the linear target. Tensor-core programs keep
the stand-in unless NX2NAVI_NATIVE_TENSOR=1, because their lowering does not match the hardware yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 05:04:39 -05:00
Valiantsin Dzerakh
0478c13e45 Import the base tree (MIT, see LICENSE) 2026-11-07 05:04:38 -05:00