Engine: native presets K and M in the D3D12 shim, wider game coverage
A standalone Vulkan inference engine (engine/) for DLSS presets K and M that runs from weights extracted from the user's own nvngx_dlss.dll, with d4r's own input, network and reconstruction shaders or the native HIP network layers, recorded into the game's command list by the shim. Opt-in ([Engine] Enabled / D4R_ENGINE=1); anything uncovered falls back to the CUDA/ZLUDA path with the reason logged. Byte-identical to NGX's CUDA backend under the phase-capable reference (1706x960 -> 2560x1440, native HIP network, eleven frames, RX 9070 XT): - K render- and display-resolution motion vectors, HDR and LDR - K game-supplied exposure and automatic exposure with any pre-exposure and exposure scale (one residual: effective exposure exactly 2 or 4) - K and M with the DLSS indicator's inverted-axis parameters - M with any exposure settings (NGX ignores them for M) K packages need the current compile_k.py (marker D4RO0003). Also: HIP shared buffers are pooled across feature recreation (ROCm leaks destroyed imports), hipnet.bin must match the preset, M-only games do not load the K model, install_d4r_runtime.sh stages k, k-ldr, m, m-ldr with hip/, the activation table has a generator (gen_activation_m.py), and package_release.sh can bundle the engine's shaders (never its weights). Signed-off-by: woutermans <[email protected]>
This commit is contained in:
1 parent
16cfc1f063
commit
e0d1549a21
82 files changed
+13335
-96
No files matched your search
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate activation_m.glsl's ACT table: binary16 sigmoid, tanh and gate of every E4M3 code.
|
||||
|
||||
usage: gen_activation_m.py print the ACT declaration
|
||||
gen_activation_m.py --check exit 1 unless engine/activation_m.glsl holds exactly this table
|
||||
|
||||
Row c is uvec2(tanh << 16 | sigmoid, gate) for the E4M3 value of code c:
|
||||
sigmoid 1 / (1 + exp2(-1.442695 * x)) in f32, rounded to binary16
|
||||
tanh correctly rounded binary16 tanh(x)
|
||||
gate .5 * tanh(.5 * x) + .5 with each operation rounded to binary16
|
||||
The NaN codes (127, 255) give quiet NaN; the sigmoid keeps the input's sign, as f32 arithmetic propagates it.
|
||||
"""
|
||||
import math
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
GLSL = Path(__file__).resolve().parent / 'activation_m.glsl'
|
||||
NAN_ROWS = {127: (0x7e007e00, 0x7e00), 255: (0x7e00fe00, 0x7e00)}
|
||||
|
||||
|
||||
def e4m3(code):
|
||||
sign = -1.0 if code & 128 else 1.0
|
||||
exponent, mantissa = (code >> 3) & 15, code & 7
|
||||
if exponent == 0:
|
||||
return sign * mantissa / 8 * 2.0 ** -6
|
||||
return sign * (1 + mantissa / 8) * 2.0 ** (exponent - 7)
|
||||
|
||||
|
||||
def bits(value):
|
||||
return int(np.array(value, dtype=np.float16).view(np.uint16))
|
||||
|
||||
|
||||
def row(code):
|
||||
if code in NAN_ROWS:
|
||||
return NAN_ROWS[code]
|
||||
x = e4m3(code)
|
||||
with np.errstate(over='ignore'):
|
||||
sigmoid = np.float32(1) / (np.float32(1) + np.exp2(np.float32(-1.442695) * np.float32(x), dtype=np.float32))
|
||||
# float64 tanh rounded once to binary16 is correctly rounded for every E4M3 input (no value lies near a tie).
|
||||
tanh = np.float16(math.tanh(x))
|
||||
half = np.float16(0.5)
|
||||
gate = np.float16(np.float16(half * np.float16(math.tanh(float(half * np.float16(x))))) + half)
|
||||
return bits(tanh) << 16 | bits(sigmoid), bits(gate)
|
||||
|
||||
|
||||
def declaration():
|
||||
rows = ',\n'.join(f' uvec2(0x{x:08x}u, 0x{y:08x}u)' for x, y in map(row, range(256)))
|
||||
return f'const uvec2 ACT[256] = uvec2[256](\n{rows}\n);'
|
||||
|
||||
|
||||
def main(argv):
|
||||
if argv == ['--check']:
|
||||
match = re.search(r'const uvec2 ACT\[256\] = uvec2\[256\]\(.*?\n\);', GLSL.read_text(), re.S)
|
||||
if match is None or match.group(0) != declaration():
|
||||
print(f'{GLSL} does not hold the generated table', file=sys.stderr)
|
||||
return 1
|
||||
return 0
|
||||
if argv:
|
||||
sys.exit(__doc__)
|
||||
print(declaration())
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
Reference in new issue
Block a user