The fully native release. Ninja Gaiden II's graphics now run entirely inside ng2.exe: the game's Xbox 360 GPU
commands are decoded on its own thread and drawn by a Direct3D 12 renderer built into the program. There is no GPU
plugin any more (rexgpu-xenos.dll is gone). Checked by walking every chapter from a full set of saves on the native
renderer - no unhandled command, no failed draw - by playing the Chapter 10 boss fight, and by walking six chapters
again on this exact build.
v1.0.25, v1.1.0 and v1.1.1 were test builds and were never published, so their notes are included below, newest
first. (v1.1.0's "Native renderer" settings row was retired in v1.1.1: the native renderer is now the only path.)
v1.1.2 - 2026-09-28
Changed - drawing moved off the game's thread
The game's graphics commands are still read on the game's own thread, but the
Direct3D 12 recording of its draws now happens on a thread of its own, fed in
order, with every fence and interrupt kept behind the draws before it. In the
heaviest scene measured (the Chapter 4 boss fight, about 3,000 draws a frame)
that takes about 4.4 ms a frame off the game's thread, and the game never
waits for the drawing thread. The frame rate was already a steady 60; this is
headroom for high internal resolutions and busy fights.
Fixed - hitches when a stage streams in new enhanced textures
With the texture pack on, walking into a new area could freeze the picture
for 50-200 ms (3-4 times in four minutes of Chapter 14). The pack prepares a
stage's textures ahead of time, but only up to 1.5 GB, and a whole stage can
need more (Chapter 14: 2.2 GB), so the rest were built during play. The limit
now follows the graphics card - 30% of its video memory, up to 4 GB - so a
card with enough memory prepares the whole stage: 0 such hitches in the same
walks. Cards with less memory get the same budget as before.
Changed - fully native, now also in the documentation
The README no longer describes a GPU plugin: the renderer is part of this
project and built into ng2.exe.
v1.1.1 - 2026-09-28
Changed - fully native: rexgpu-xenos.dll is gone
The game's graphics now run entirely inside ng2.exe: the console's command
stream is read by the program itself and every frame is drawn by its own
Direct3D 12 renderer. rexgpu-xenos.dll is no longer shipped or loaded, and
the "Native renderer" settings row is retired - there is only one path. A
machine without Direct3D 12 gets a message box instead of a black window.
Checked by walking every chapter from the saves list (no unhandled command,
no failed draw) and by playing the Chapter 10 boss fight.
Frames are handed to the window by a present thread of their own, so the
game thread no longer waits for the copy to the screen.
Added - F10 "Internal resolution"
One row listing real render resolutions up to 8K (the world at up to 720p
times an integer scale).
Fixed
- Chapter 10: the boss cinematic went black after its first frame and Ryu's
shadow was a box. The renderer now uses the pixel-shader render-target
path (ROV) the game's settings ask for; it had silently fallen back to a
path this game cannot use. - Ultrawide, boss health bar (verified on the Chapter 4 boss): the bar now drops
with each hit. Before, the damage showed outside the bar and the red fill
sprang back, because the bar's cut and its plain-colour layers were not
moved into the 16:9 HUD band with the rest of the bar. - Ultrawide, level start: no more flash of the stage before the loading
icon; after a chapter card the screen holds black and the level fades in
at full width. - Ultrawide, scene transitions (Chapter 7 door and others): full-screen
transition images are no longer squeezed into the centre with the world
showing on the sides. - Enhanced-texture pack: replacement textures are released with the rest of
the texture cache and count toward its memory budget, fixing a memory
climb over long sessions.
v1.1.0 - 2026-09-27
Added - the native renderer, in the game's own window
A new settings row, "Native renderer" (on by default, restart required),
runs the game's graphics on the renderer built into ng2.exe: the plugin
still parses the console's command stream, but every frame is drawn by the
copy of its Direct3D 12 backend compiled into the program, on the same GPU
device and queue, and handed to the window's presenter through the plugin's
swap - so the picture, the ultrawide fill and pillarbox, the letterbox, the
F10 menu, the on-screen readouts and the controller all stay in the one
window exactly as before. Turning the row off returns to the v1.0.25 plugin
path.
This is a test cut of the native path: the same frames as the plugin path
(the two backends are the same code), with the plugin's own GPU work skipped.
Everything shipped through v1.0.25 rides along: the enhanced-texture pack
with its stage warming, GPU-ready prebuild and per-chapter pre-creation (the
prebuild's VRAM budget now follows the graphics card - 30% of its local
memory, 512 MB to 4 GB - on top of the size cap, for smaller cards), the
ultrawide fades, the 60 fps path, the F10 settings as tagged by the census.
The 5-second [ngpu] ONE WINDOW log line counts the frames the native
backend handed over and the frames the plugin presented from them; the
[ngpu] PACK COUNTERS line shows the pack replacing textures under the
native path.
Changed - Ultrawide: a fade between the full-width and the 16:9 pictures
Every switch between the full-width picture (gameplay) and the 16:9 one
(menus, the continue screen after a death, videos) now fades to black
and back over about a fifth of a second each way instead of cutting, on
both renderers. The game's own layout and the screen's letterbox change
together at full black, so nothing is ever shown stretched.
Fixed - Ultrawide: the Start menu is shown at 16:9
On an ultrawide display the Start (weapons / items) menu's drifting red mist
reached the edges of the screen on the native renderer, where the plugin
path had kept it inside the 16:9 band. The mist is two scrolling pictures
three times the width of the menu's own canvas, and on a wide screen their
outer parts are what shows at the sides. The menu is now treated like every
other menu in the game: a frame that draws the mist is shown pillarboxed at
16:9, on both renderers, with the world behind it at its console field of
view; leaving the menu returns the picture to the full width within a few
frames. Detected from the draw itself, so it does not depend on the two game
flags that v1.0.25 stopped using for this menu.
v1.0.25 - 2026-09-26
Fixed - the enhanced-textures indicator said the pack was idle while it was working
With the texture pack on, the settings menu's status line read "Enhanced
textures: ON - nothing on this screen is in the pack yet" and the on-screen
notice "0 enhanced loaded" - in every release from v1.0.20 to v1.0.24 as
played, and most likely since v1.0.13 - while the pack was in fact replacing
textures on screen (a trace on the Chapter 1 route counted 752 replacements
against an indicator of 0). The counter behind both lines was incremented
only on an older replacement path that the pack's normal path (resolving
each texture by its content as it loads) never takes. The counter now counts
that path, so the status line reads "ON and in use" and the notice shows the
number of enhanced textures loaded. The pack itself was never affected: the
textures on screen were the enhanced ones all along.
The 5-second [swap] line in the log also carries the two counters
(texpack registry replaced N original M), so a log says what the indicator
would show.
Fixed - Ultrawide: the pause menu no longer flips between full width and 16:9, and the fade back into the game covers the screen
Opening the pause / weapons menu switched the picture to 16:9, and on the way
back the fade played inside the 16:9 band before the sides snapped in. Worse,
the switch was not steady: the two game flags that signalled "paused" toggle
about once a second while the menu is open, so the screen swung between full
width and pillarbox for as long as the menu stayed up (measured in every
release since v1.0.19, which introduced those flags). The menu is now treated
like any other 2D screen over the game - drawn in its 16:9 band over the
ultrawide world, with nothing switching underneath it - so the darkening fade
in and out of the menu covers the whole screen. Set NG2_UW_PAUSE_16_9=1 in the
environment for the old behaviour.
A frame that draws the game's fade-to-black now counts as ultrawide even when
no world is behind it, so the fades that bracket a video or a scene change
cover the full width instead of the 16:9 band.
Improved - The game's own textures are prepared at a chapter load, with or without the pack
Even with the enhanced textures off, a scene streaming in made the game
create hundreds of textures on the rendering thread in one frame (542 on
arrival in Chapter 1: a 145 ms frame). The game now remembers, per chapter,
the shapes of the textures it created, and at the next load of that chapter
a worker prepares them ahead of time (within texture_precreate_mb, 512 by
default), while the game itself is not creating anything; the streaming
burst then takes ready-made textures. Measured on the same route with the
pack off: the arrival frame 145 ms -> 38 ms (the 542 creations 102 ms ->
2 ms), the whole route's worst frame 145 -> 72 ms. The first visit to a
chapter records; every visit after that benefits.
With the pack on, the stage pre-cache now goes further than reading files:
the pack's textures for the stage are built ready for the GPU during the
load (within texture_pack_prebuild_mb, 1536 by default), so a texture
whose content matches swaps to the finished one with no read, no creation
and no upload in play.
Fixed - Antialiasing now changes immediately from the settings screen, and the rows that need a restart say so
The Antialiasing row said the change applies at once, and the game did push
it, but the GPU plugin read the value once at startup and refused changes
after that - so a new setting only showed up on the next launch. The plugin
now takes the change on the next frame. Supersampling, anisotropic filtering
and the other GPU rows are decided when the renderer starts and cannot be
rebuilt underneath a running game; those rows now carry a red "restart
required" note beside the value (the note existed but was never drawn).
A census of every row on the screen (tools/f10_census.py: each row, the
setting it edits, the value the game hands the renderer at launch and while
running, and where the renderer reads it) found two more: "Dither the
output" and "Extra sharpness" are read by the presenter once at start-up, so
changing them in-game does nothing until a restart - both rows now carry the
restart note (and the sharpness value is now handed over at launch, which it
never was); and "Fuzzy alpha test" reaches only shaders compiled after the
change, so it carries the note too.
Everything else on the screen reaches what it should, live or at launch as
labelled.
The anisotropic filtering labels were one level high: "1x" turned filtering
off, "16x" gave 8x, and true 16x could not be chosen (the Fable II team found
the same in its own menu). The row now offers Default (4x), Off, 2x, 4x, 8x
and 16x, and a saved value keeps the strength it always had - a saved "16x"
was 8x and now reads "8x".
Improved - Far less stutter when a scene streams in with the texture pack on
When a scene loads, the game asks for hundreds of textures in one frame. With
the enhanced-textures pack on, every one of them also had its pack file read
and its GPU resources created on the rendering thread, inside that frame. On
arrival in Chapter 1 that was a single 1.2-second frame (572 textures, 413 of
them from the pack), and every later streaming point cost 300-900 ms.
The pack's work now happens on worker threads: the file is read and the
resources are created off the rendering thread - mostly taken from a pool
the worker fills ahead of time for the shapes the pack holds - and the
enhanced texture is swapped in a frame or two later; the game's own texture
shows until then, at native resolution. The worker also stays off the GPU
device while the game itself is creating textures in a burst, because any
concurrent creation doubled the game's own creation cost.
Measured on the same route, the shipped build twice against the new one: the
arrival frame 1230/1221 ms before, 286 ms after; the later streaming frames
873/631/474/290 ms before, 20/69/78/36 ms after; the time the rendering
thread spent inside texture loads over the whole route 4.3/3.8 s before,
0.4 s after; 5-second windows with a frame over 100 ms, 7/9 before, 2 after.
What remains of the arrival frame is the game's own creation of 542
textures (132 ms) plus their decode (118 ms).
Settings for the curious (Advanced): texture_pack_async (on),
texture_pack_apply_per_frame (24, the replacements a frame swaps in) and
texture_pack_spare_mb (256, video memory for the pre-created pool). The
[hitch] and [swap] log lines now say how much of a slow frame went into
texture creation, texture loading and pack reads.
Installing: unzip and run ng2.exe. You supply your own disc rip in game\ - no game data is included or
distributed here. A GPU with Direct3D 12 is required.
Upgrading: unzip over your existing install, or use the in-game updater. Settings, saves and texture packs are
untouched. An old rexgpu-xenos.dll left in the folder is no longer loaded and can be deleted.