Expand Windows GPU support, add native FSR RR, and improve SR interop
Add a native D3D12 FSR Ray Regeneration route for gfx1200/gfx1201, using the game's device and queue with embedded HLSL guide preparation and output composition. Preserve the vkd3d compatibility route for RDNA3 and expose explicit route overrides and diagnostics. Improve Windows runtime compatibility: - Retry rejected application-ID initialization with a project identity. - Defer expensive RR backend creation until feature creation. - Recover from transient submission failures without disabling later frames. - Add shared-buffer export fallbacks through explicit heaps and a private device on the same adapter. - Safely evict old RR descriptor sets when input views change. - Treat requested RR presets as hints when a configured model is available. - Expand SR/RR input formats and handle diffuse/specular hit distances, packed normals, depth-stencil resources, and unused FSR guides. Reduce SR overhead by batching output downloads and format conversion under one completion wait. Optimize strict M enc2/tube attention with bounded FP32 accumulation and the original FP64 fallback for ambiguous rounding cases. Extend RDNA4 tooling with gfx1200/gfx1201 native FP8 RR model builds, capability checks, architecture-aware deployment, and experimental K/M kernel paths. Require matching model and runtime arithmetic families. Add optional embedded FSR shader optimizations keyed by shader hash and exact original SPIR-V contents. Preserve reflected metadata and record optimizer provenance, artifact hashes, and cache identity. Simplify Windows installation with automatic backend dependency downloads, download progress and ETA, backed-up absolute OptiScaler library paths, and recovery from interrupted RR model builds. Add build-kernels.bat and a kernels-only build matrix for all eleven registered RDNA targets, with code-object target validation and SHA256 manifests. Expand conversion probes, numerical stress tests, temporal benchmark tooling, installer/deployment tests, and setup documentation. Document synthetic regression and timing results, experimental build options, and remaining RDNA4 hardware validation requirements.
This commit is contained in:
1 parent
a617c818de
commit
ac4ee6c225
67 files changed
+3147
-326
No files matched your search
@@ -16,6 +16,7 @@ import hashlib
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -44,11 +45,98 @@ def git(args, cwd, log, identity=False):
|
||||
run(prefix + list(args), cwd=cwd, log=log)
|
||||
|
||||
|
||||
def generate_shader_overrides(source, output, shader_dump, optimizer, hashes, log, variants=()):
|
||||
"""Embed local, measured optimizations only when the original translation matches exactly."""
|
||||
if not hashes:
|
||||
(source / 'libs/vkd3d-shader/d4r_shader_overrides.h').write_text(
|
||||
'/* Generated by tools/windows/build_fsr_payload.py. No local overrides selected. */\n'
|
||||
'static bool d4r_shader_replace_builtin(vkd3d_shader_hash_t hash, const void *original,\n'
|
||||
' size_t original_size, const void **data, size_t *size)\n{\n'
|
||||
' (void)hash; (void)original; (void)original_size; (void)data; (void)size;\n'
|
||||
' return false;\n}\n')
|
||||
return {}
|
||||
if shader_dump is None or optimizer is None:
|
||||
raise ValueError('--optimize-shader requires --shader-dump and --spirv-opt')
|
||||
records = {}
|
||||
arrays = []
|
||||
entries = []
|
||||
inputs = output / 'shader-sources'
|
||||
inputs.mkdir()
|
||||
for shader_hash, variant in ((h, v) for h in sorted(set(hashes)) for v in range(1 + len(variants))):
|
||||
if len(shader_hash) != 16 or any(c not in '0123456789abcdef' for c in shader_hash):
|
||||
raise ValueError('shader hash must contain 16 lowercase hexadecimal digits')
|
||||
original = ([shader_dump] + list(variants))[variant] / (shader_hash + '.spv')
|
||||
variant_inputs = inputs if variant == 0 else inputs / ('variant-' + str(variant))
|
||||
variant_inputs.mkdir(exist_ok=True)
|
||||
symbol = shader_hash if variant == 0 else shader_hash + '_' + str(variant)
|
||||
optimized = variant_inputs / (shader_hash + '.optimized.spv')
|
||||
run([optimizer, '--target-env=vulkan1.3', '-O', original, '-o', optimized], log=log)
|
||||
validator = optimizer.with_name('spirv-val.exe')
|
||||
run([validator, '--target-env', 'vulkan1.3', optimized], log=log)
|
||||
shutil.copy2(original, variant_inputs / original.name)
|
||||
for kind, path in (('original', original), ('optimized', optimized)):
|
||||
data = path.read_bytes()
|
||||
if len(data) % 4 or data[:4] != b'\x03\x02\x23\x07':
|
||||
raise ValueError('invalid SPIR-V: ' + str(path))
|
||||
words = struct.unpack('<%dI' % (len(data) // 4), data)
|
||||
rows = [', '.join('0x%08xu' % word for word in words[i:i + 8]) for i in range(0, len(words), 8)]
|
||||
arrays.append('static const uint32_t d4r_%s_%s[] = {\n%s\n};\n' %
|
||||
(kind, symbol, ',\n'.join(rows)))
|
||||
entries.append(' {0x%sULL, d4r_original_%s, sizeof(d4r_original_%s), '
|
||||
'd4r_optimized_%s, sizeof(d4r_optimized_%s)},' % (shader_hash, symbol, symbol, symbol, symbol))
|
||||
records[symbol] = {'originalSha256': sha(original), 'optimizedSha256': sha(optimized)}
|
||||
header = '''/* Local shader optimizations. Generated by tools/windows/build_fsr_payload.py. */
|
||||
''' + ''.join(arrays) + '''
|
||||
static const struct d4r_shader_override {
|
||||
vkd3d_shader_hash_t hash;
|
||||
const void *original;
|
||||
size_t original_size;
|
||||
const void *optimized;
|
||||
size_t optimized_size;
|
||||
} d4r_shader_overrides[] = {
|
||||
''' + '\n'.join(entries) + '''
|
||||
};
|
||||
static bool d4r_shader_replace_builtin(vkd3d_shader_hash_t hash, const void *original,
|
||||
size_t original_size, const void **data, size_t *size)
|
||||
{
|
||||
char disabled[2];
|
||||
unsigned int i;
|
||||
if (vkd3d_get_env_var("D4R_FSR_DISABLE_BUILTIN_SHADERS", disabled, sizeof(disabled)))
|
||||
return false;
|
||||
for (i = 0; i < ARRAY_SIZE(d4r_shader_overrides); ++i)
|
||||
{
|
||||
const struct d4r_shader_override *entry = &d4r_shader_overrides[i];
|
||||
void *buffer;
|
||||
if (entry->hash != hash || entry->original_size != original_size ||
|
||||
memcmp(entry->original, original, original_size))
|
||||
continue;
|
||||
if (!(buffer = vkd3d_malloc(entry->optimized_size)))
|
||||
return false;
|
||||
memcpy(buffer, entry->optimized, entry->optimized_size);
|
||||
*data = buffer;
|
||||
*size = entry->optimized_size;
|
||||
INFO("d4r: using validated local optimization for shader %016"PRIx64".\\n", hash);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
'''
|
||||
(source / 'libs/vkd3d-shader/d4r_shader_overrides.h').write_text(header)
|
||||
(inputs / 'd4r_shader_overrides.h').write_text(header)
|
||||
records['optimizerSha256'] = sha(optimizer)
|
||||
(inputs / 'manifest.json').write_text(json.dumps(records, indent=2) + '\n')
|
||||
return records
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--output', required=True, type=lambda p: Path(p).resolve())
|
||||
parser.add_argument('--source', type=lambda p: Path(p).resolve(),
|
||||
help='reuse an existing vkd3d-proton clone (must be a checkout of the pinned commit); default: fresh clone under --output/_work')
|
||||
parser.add_argument('--shader-dump', type=lambda p: Path(p).resolve(), help='original SPIR-V from this translator/device')
|
||||
parser.add_argument('--shader-variant', action='append', default=[], type=lambda p: Path(p).resolve(), help='additional exact translation variant directory')
|
||||
parser.add_argument('--spirv-opt', type=lambda p: Path(p).resolve(), help='local spirv-opt.exe used for measured optimizations')
|
||||
parser.add_argument('--optimize-shader', action='append', default=[], metavar='HASH', help='embed a measured -O shader; repeat for each validated winner')
|
||||
args = parser.parse_args()
|
||||
if not args.output.is_relative_to((repo / 'build').resolve()):
|
||||
parser.error('output must stay under ignored build/')
|
||||
@@ -85,12 +173,25 @@ def main():
|
||||
if not ancestor:
|
||||
git(['cherry-pick', '-x'] + listing, dxil, log, identity=True)
|
||||
# libc++ include fixes (GCC pulled these in transitively; libc++ does not)
|
||||
# and late shader replacement, preserving dxil-spirv's reflected metadata.
|
||||
for patch, where in (('0001-dxil-spirv-include-exception-for-libcxx.patch', dxil),
|
||||
('0002-dxbc-spirv-include-new-for-libcxx.patch', dxil / 'subprojects/dxbc-spirv')):
|
||||
('0002-dxbc-spirv-include-new-for-libcxx.patch', dxil / 'subprojects/dxbc-spirv'),
|
||||
('0003-preserve-meta-for-shader-overrides.patch', source),
|
||||
('0004-support-local-optimized-shaders.patch', source)):
|
||||
full = repo / 'patches/vkd3d-proton-windows' / patch
|
||||
check = subprocess.run(['git', 'apply', '--check', '--reverse', str(full)], cwd=where, capture_output=True)
|
||||
if check.returncode: # not applied yet
|
||||
git(['apply', full], where, log)
|
||||
optimized_shaders = generate_shader_overrides(source, args.output, args.shader_dump, args.spirv_opt,
|
||||
args.optimize_shader, log, args.shader_variant)
|
||||
# Cache identities must include local patches and shader contents, not only upstream HEAD.
|
||||
build_identity = hashlib.sha256()
|
||||
build_identity.update((VKD3D_COMMIT + DXIL_FSR_MERGE).encode())
|
||||
for patch in sorted((repo / 'patches/vkd3d-proton-windows').glob('*.patch')):
|
||||
build_identity.update(patch.read_bytes())
|
||||
build_identity.update(json.dumps(optimized_shaders, sort_keys=True).encode())
|
||||
build_id = build_identity.hexdigest()[:16]
|
||||
(source / 'vkd3d_build.h.in').write_text('#include <stdint.h>\nstatic const uint64_t vkd3d_build = 0x' + build_id + ';\n')
|
||||
escaped = lambda path: str(path).replace('\\', '/')
|
||||
cross = work / 'cross.txt'
|
||||
cross.write_text('\n'.join([
|
||||
@@ -129,15 +230,18 @@ def main():
|
||||
'fsr/d4r_vkd3d_core.dll is vkd3d-proton (LGPL-2.1) built for Windows by tools/windows/build_fsr_payload.py.',
|
||||
'Corresponding source: ' + VKD3D_URL + ' at ' + VKD3D_COMMIT + ',',
|
||||
'dxil-spirv with upstream PR 307 (merge ' + DXIL_FSR_MERGE + ') cherry-picked, and the patches in',
|
||||
'patches/vkd3d-proton-windows/ of the d4r repository (libc++ include fixes). Build: meson cross build with',
|
||||
'patches/vkd3d-proton-windows/ of the d4r repository (libc++ fixes and metadata-preserving shader overrides).',
|
||||
'Build: meson cross build with',
|
||||
'llvm-mingw clang, -Denable_extended_emulation=true, buildtype release; the DLL is stripped and renamed.',
|
||||
'Built HEADs: ' + json.dumps(heads), 'Patches: ' + json.dumps(patches),
|
||||
'Cache build ID: ' + build_id, 'Local optimized shaders: ' + json.dumps(optimized_shaders),
|
||||
'Local shader source inputs and generated header, when selected: shader-sources/.',
|
||||
'fsr/amdxc64.dll is d4r original code (tools/windows/amdxc64_shim). It is not AMD software.', '']))
|
||||
files = {str(p.relative_to(args.output)).replace('\\', '/'): sha(p) for p in sorted(args.output.rglob('*'))
|
||||
if p.is_file() and '_work' not in p.relative_to(args.output).parts}
|
||||
(args.output / 'fsr-payload.json').write_text(json.dumps(dict(
|
||||
schema=1, kind='d4r-fsr-payload', amdDenoiserBundled=False, vkd3dProtonCommit=VKD3D_COMMIT, dxilSpirvFsrMerge=DXIL_FSR_MERGE,
|
||||
builtHeads=heads, patches=patches, files=files), indent=2) + '\n')
|
||||
builtHeads=heads, patches=patches, optimizedShaders=optimized_shaders, cacheBuildId=build_id, files=files), indent=2) + '\n')
|
||||
print(json.dumps(files, indent=2))
|
||||
print('FSR_PAYLOAD_BUILT ' + str(args.output))
|
||||
|
||||
|
||||
Reference in new issue
Block a user