Enable experimental native Windows RDNA3 and RDNA4 targets

Share explicit target metadata across build/runtime/package guards, preserve native gfx11 WMMA with a Windows LDS lane exchange, select HIP devices by D3D12 LUID, and reject wrong-target/vkd3d installations before changing game files. Review all issue #10 logs and document compile-only coverage plus RX9070XT regressions.

Co-authored-by: realdody <[email protected]>
This commit is contained in:
xdfnx-devandrealdody committed 2026-10-02 17:10:42 +03:00
1 parent 98de8e3a3e
commit 3fa963fd1b
32 files changed
+494 -162

No files matched your search

+4 -3
View File
@@ -1,4 +1,4 @@
"""Build a private RDNA4 texture override from the user's local DLSS DLL.
"""Build a private target-specific texture override from the user's local DLSS DLL.
The resulting PTX/code object contains NVIDIA code and must remain local.
No Wine, shell script, GPU, CUDA SDK or system installation is required.
@@ -13,13 +13,14 @@ import re
import shutil
import subprocess
import sys
from gpu_targets import TARGETS
def require_code_object_target(path, target):
with path.open('rb') as file:
header = file.read(64)
if (len(header) != 64 or header[:6] != b'\x7fELF\x02\x01' or
header[18:20] != b'\xe0\x00' or header[48] != {'gfx1200': 0x48, 'gfx1201': 0x4e}[target]):
header[18:20] != b'\xe0\x00' or header[48] != TARGETS[target]['elfMachine']):
raise RuntimeError(f'Code object does not target {target}: {path}')
@@ -30,7 +31,7 @@ def main():
parser.add_argument('--zluda-root', type=pathlib.Path, required=True)
parser.add_argument('--kernel', required=True)
parser.add_argument('--output-directory', type=pathlib.Path, required=True)
parser.add_argument('--gpu-arch', choices=['gfx1200', 'gfx1201'], default='gfx1201')
parser.add_argument('--gpu-arch', choices=tuple(TARGETS), default='gfx1201')
parser.add_argument('--shader-mode', choices=['cu', 'wgp'], default='cu')
args = parser.parse_args()
if not re.fullmatch(r'hiluma_engine_(?:output_depth(?:inv|reg)_mv(?:hi|lo)_(?:hdr|ldr)(?:_max)?|'
+1 -1
View File
@@ -87,7 +87,7 @@ API unsigned NVSDK_NGX_D3D12_GetFeatureRequirements(IDXGIAdapter* adapter, const
DXGI_ADAPTER_DESC desc{}; d4r::win::dx(adapter->GetDesc(&desc), "NGX requirements adapter");
// OptiScaler can override the DXGI vendor ID. The physical HIP
// architecture and full adapter LUID are the authoritative identity.
d4r::diag::HipApi hip(d4r::win::env_path("D4R_HIP_ROOT")); hipDeviceProp_t props{}; hip.select_architecture(-1,props);
d4r::diag::HipApi hip(d4r::win::env_path("D4R_HIP_ROOT")); hipDeviceProp_t props{}; hip.select_architecture(-1,props,&desc.AdapterLuid);
requirements->FeatureSupported = std::memcmp(&desc.AdapterLuid,props.luid,sizeof(LUID)) ? 4u : 0u;
std::strcpy(requirements->MinOSVersion,"10.0.22000.0");
std::printf("D4R_REQUIREMENTS feature=%u support=%u architecture=%s\n",info->FeatureID,requirements->FeatureSupported,d4r::diag::HipApi::target_arch());
+16
View File
@@ -0,0 +1,16 @@
{
"schema": 1,
"targets": [
{"architecture":"gfx1100","elfMachine":65,"isaMajor":11,"family":"RDNA3"},
{"architecture":"gfx1101","elfMachine":70,"isaMajor":11,"family":"RDNA3"},
{"architecture":"gfx1102","elfMachine":71,"isaMajor":11,"family":"RDNA3"},
{"architecture":"gfx1103","elfMachine":68,"isaMajor":11,"family":"RDNA3"},
{"architecture":"gfx1150","elfMachine":67,"isaMajor":11,"family":"RDNA3.5"},
{"architecture":"gfx1151","elfMachine":74,"isaMajor":11,"family":"RDNA3.5"},
{"architecture":"gfx1152","elfMachine":85,"isaMajor":11,"family":"RDNA3.5"},
{"architecture":"gfx1153","elfMachine":88,"isaMajor":11,"family":"RDNA3.5"},
{"architecture":"gfx1154","elfMachine":87,"isaMajor":11,"family":"RDNA3.5"},
{"architecture":"gfx1200","elfMachine":72,"isaMajor":12,"family":"RDNA4"},
{"architecture":"gfx1201","elfMachine":78,"isaMajor":12,"family":"RDNA4"}
]
}
+57
View File
@@ -0,0 +1,57 @@
#include "hip_api.h"
#include <fstream>
#include <sstream>
#include <iomanip>
static std::string json_string(const std::string& value) {
std::ostringstream out; out << '"';
for (unsigned char c : value) {
if (c == '"' || c == '\\') out << '\\' << char(c);
else if (c < 32) out << "\\u" << std::hex << std::setw(4) << std::setfill('0') << unsigned(c);
else out << char(c);
}
out << '"'; return out.str();
}
int main(int argc, char** argv) {
using namespace d4r::diag;
start();
try {
Args args(argc, argv);
if (args.output_dir.empty()) throw std::runtime_error("--output-dir is required");
for (const char* name : {"HSA_OVERRIDE_GFX_VERSION", "HSA_OVERRIDE_GFX_VERSION_0"})
if (std::getenv(name)) throw std::runtime_error(std::string("Unset architecture override ") + name);
HipApi hip(args.hip_root);
hip.check(hip.hipInit(0), "hipInit(inventory)");
int count=0, version=0, driver=0;
hip.check(hip.hipRuntimeGetVersion(&version), "hipRuntimeGetVersion");
hip.check(hip.hipDriverGetVersion(&driver), "hipDriverGetVersion");
std::printf("GPU_INVENTORY_RUNTIME runtime=%d driver_api=%d headers=%d.%d.%d sizeof(properties)=%zu\n",
version,driver,HIP_VERSION_MAJOR,HIP_VERSION_MINOR,HIP_VERSION_PATCH,sizeof(hipDeviceProp_t));
hip.check(hip.hipGetDeviceCount(&count), "hipGetDeviceCount");
std::ostringstream json;
json << "{\"schema\":1,\"runtimeVersion\":" << version << ",\"driverApiVersion\":" << driver << ",\"compiledTarget\":"
<< json_string(D4R_TARGET_ARCH) << ",\"gpuWorkExecuted\":false,\"devices\":[";
for (int i=0; i<count; ++i) {
hipDeviceProp_t p{}; hip.check(hip.hipGetDeviceProperties(&p,i), "hipGetDevicePropertiesR0600");
const auto arch=gpu_architecture(p.gcnArchName);
std::printf("GPU_INVENTORY ordinal=%d name=%s gcnArchName=%s wave=%d build_eligible=%d\n",
i,p.name,p.gcnArchName,p.warpSize,supported_gpu_target(arch));
if (i) json << ',';
json << "{\"ordinal\":" << i << ",\"name\":" << json_string(p.name)
<< ",\"gcnArchName\":" << json_string(p.gcnArchName) << ",\"architecture\":" << json_string(arch)
<< ",\"wavefrontSize\":" << p.warpSize << ",\"vramBytes\":" << p.totalGlobalMem
<< ",\"buildEligible\":" << (supported_gpu_target(arch) ? "true" : "false") << '}';
}
json << "]}\n";
std::filesystem::create_directories(wide(args.output_dir));
std::ofstream file(std::filesystem::path(wide(args.output_dir))/L"gpu-inventory.json",std::ios::binary);
file << json.str(); file.close();
if (!file) throw std::runtime_error("Cannot write GPU inventory");
if (!count) throw std::runtime_error("HIP reports no devices");
loaded_modules();
std::printf("PASS GPU_INVENTORY devices=%d gpu_work_executed=0\n",count);
return 0;
} catch (const std::exception& error) {
std::fprintf(stderr,"FAIL GPU_INVENTORY %s\n",error.what()); loaded_modules(); return 4;
}
}
+5 -6
View File
@@ -4,6 +4,7 @@
#include <fstream>
#include <stdexcept>
#include <string>
#include "gpu_targets.generated.h"
#ifndef D4R_TARGET_ARCH
#define D4R_TARGET_ARCH "gfx1201"
@@ -11,7 +12,8 @@
namespace d4r::diag {
inline bool supported_gpu_target(const std::string& target) {
return target == "gfx1200" || target == "gfx1201";
for (const auto& row : gpu_targets) if (target == row.architecture) return true;
return false;
}
inline std::string gpu_architecture(const std::string& name) {
return name.substr(0, name.find(':'));
@@ -29,11 +31,8 @@ inline std::string code_object_target(const std::filesystem::path& path) {
header[0] != 0x7f || header[1] != 'E' || header[2] != 'L' || header[3] != 'F' ||
header[4] != 2 || header[5] != 1 || header[18] != 0xe0 || header[19] != 0)
throw std::runtime_error("Invalid AMDGPU ELF64 code object: " + path.string());
switch (header[48]) {
case 0x48: return "gfx1200";
case 0x4e: return "gfx1201";
default: throw std::runtime_error("Unsupported AMDGPU code-object target: " + path.string());
}
for (const auto& row : gpu_targets) if (header[48] == row.elf_machine) return row.architecture;
throw std::runtime_error("Unsupported AMDGPU code-object target: " + path.string());
}
inline void require_code_object_target(const std::filesystem::path& path, const std::string& expected) {
require_gpu_target(code_object_target(path), expected);
+3 -2
View File
@@ -5,10 +5,11 @@ int main(int argc, char** argv) {
using namespace d4r::diag;
try {
unsigned rejected = 0, objects = 0;
for (const char* target : {"gfx1200", "gfx1201"}) {
for (const auto& info : gpu_targets) {
const char* target = info.architecture;
require_gpu_target(target, target);
require_gpu_target(std::string(target) + ":xnack-:sramecc-", target);
for (const char* invalid : {"gfx1101", "gfx12000", "gfx1202", "gfx1250", ""}) {
for (const char* invalid : {"gfx1030", "gfx1104", "gfx1155", "gfx1170", "gfx12000", "gfx1202", "gfx1250", ""}) {
try { require_gpu_target(invalid, target); }
catch (const std::exception&) { ++rejected; continue; }
throw std::runtime_error("Invalid GPU target accepted");
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include <array>
namespace d4r::diag {
struct GpuTarget { const char* architecture; unsigned elf_machine; unsigned isa_major; const char* family; };
inline constexpr std::array<GpuTarget, @d4r_target_count@> gpu_targets = {{
@d4r_target_cpp_entries@}};
}
+10
View File
@@ -0,0 +1,10 @@
"""Canonical Windows build target registry, shared with CMake and PowerShell."""
import json
import pathlib
data = json.loads(pathlib.Path(__file__).with_name('gpu-targets.json').read_text())
if data['schema'] != 1:
raise RuntimeError('Unsupported GPU target registry schema')
TARGETS = {row['architecture']: row for row in data['targets']}
if len(TARGETS) != len(data['targets']):
raise RuntimeError('Duplicate GPU target')
+5 -3
View File
@@ -42,7 +42,7 @@ struct HipApi {
if (result != hipSuccess) throw std::runtime_error(std::string(call) + ": " + hipGetErrorString(result));
}
static const char* target_arch() { return D4R_TARGET_ARCH; }
int select_architecture(int requested, hipDeviceProp_t& selected) const {
int select_architecture(int requested, hipDeviceProp_t& selected, const void* required_luid = nullptr) const {
// Architecture spoofing invalidates a gfx12 correctness test.
for (const char* name : {"HSA_OVERRIDE_GFX_VERSION", "HSA_OVERRIDE_GFX_VERSION_0"})
if (std::getenv(name)) throw std::runtime_error(std::string("Unset architecture override ") + name);
@@ -61,12 +61,14 @@ struct HipApi {
i, props.name, props.gcnArchName, props.warpSize, props.totalGlobalMem,
props.pciDomainID, props.pciBusID, props.pciDeviceID);
const std::string arch = props.gcnArchName;
if (gpu_architecture(arch) == target_arch() && (requested < 0 || requested == i) && found < 0) {
if (gpu_architecture(arch) == target_arch() && (requested < 0 || requested == i) && found < 0 &&
(!required_luid || std::memcmp(props.luid, required_luid, sizeof(props.luid)) == 0)) {
found = i;
selected = props;
}
}
if (found < 0) throw std::runtime_error(std::string("No selected ") + target_arch() + " device; refusing architecture substitution");
if (found < 0) throw std::runtime_error(std::string("No selected ") + target_arch() +
" device for this adapter; use the package matching the actual HIP architecture (see GPU log)");
require_gpu_target(selected.gcnArchName, target_arch());
check(hipSetDevice(found), "hipSetDevice");
std::printf("SELECTED HIP ordinal=%d architecture=%s validation=%s\n", found, target_arch(),
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Compare RDNA4 K enc1/enc2 launches with the existing numpy reference."""
"""Compare native K enc1/enc2 launches with the existing numpy reference."""
import argparse
import math
import pathlib
@@ -73,7 +73,7 @@ def main():
# after each K stage has been compared on captured DLSS weights/activations.
if full_abs > 0.001 or full_psnr < 60.0 or merged_abs > 0.001 or merged_psnr < 60.0:
raise RuntimeError(f"K {args.kernel_name} numerical mismatch against pwin_model.py")
print(f"PASS K_REFERENCE reference_layout=gfx12 kernel={args.kernel_name} "
print(f"PASS K_REFERENCE reference=logical kernel={args.kernel_name} "
"nonzero_weights=1 transformer_executed=1 nan_inf=0")
+1 -1
View File
@@ -139,7 +139,7 @@ def validate(layer, directory, output, window_count=1, real_capture=False):
if maximum > absolute_limit or psnr < 60:
worst = int(difference.argmax())
raise RuntimeError(f'K mismatch at {worst}: reference={expected[worst]}, gpu={actual[worst]}')
print(f'PASS K_REPLAY_REFERENCE kernel={layer} reference_layout=gfx12 nan_inf=0')
print(f'PASS K_REPLAY_REFERENCE kernel={layer} reference=logical nan_inf=0')
if __name__ == '__main__':
+1 -1
View File
@@ -153,7 +153,7 @@ def validate(layer, directory, output, block_count, real_capture, exact=False):
maximum, peak, psnr, steps = metrics(expected, actual, f'M_REPLAY_REFERENCE kernel={layer}')
if ((exact or not real_capture) and maximum != 0) or (real_capture and (steps.max() > 1 or psnr < 50)):
raise RuntimeError(f'M mismatch: exact synthetic / <=1 FP8 step and >=50 dB real gate; peak={peak}')
print(f'PASS M_REPLAY_REFERENCE kernel={layer} blocks={len(pairs)} reference_layout=gfx12 nan_inf=0')
print(f'PASS M_REPLAY_REFERENCE kernel={layer} blocks={len(pairs)} reference=logical nan_inf=0')
if __name__ == '__main__':
+2 -2
View File
@@ -94,9 +94,9 @@ struct Runtime {
if (!d3d) throw std::runtime_error("Null D3D12 device");
try {
hipDeviceProp_t props{};
hip.select_architecture(-1, props);
hip.verbose = cuda.verbose = !std::getenv("D4R_QUIET_API");
const auto luid = adapter_luid(d3d);
hip.select_architecture(-1, props, &luid);
hip.verbose = cuda.verbose = !std::getenv("D4R_QUIET_API");
if (std::memcmp(&luid, props.luid, sizeof(luid))) throw std::runtime_error("D3D12/HIP LUID mismatch");
cuda.check(cuda.cuInit(0), "cuInit(Windows runtime)");
int count = 0; cuda.check(cuda.cuDeviceGetCount(&count), "cuDeviceGetCount");
+18
View File
@@ -25,6 +25,7 @@ extern "C" __attribute__((global)) void d4r_wmma_gfx1201(
const unsigned int group = lane >> 4;
const _Float16* a = reinterpret_cast<const _Float16*>(a_bits);
const _Float16* b = reinterpret_cast<const _Float16*>(b_bits);
#if defined(__GFX12__)
h8 a_frag, b_frag;
f8 c_frag;
for (unsigned int i = 0; i < 8u; ++i) {
@@ -39,6 +40,23 @@ extern "C" __attribute__((global)) void d4r_wmma_gfx1201(
b_frag, a_frag, result);
for (unsigned int i = 0; i < 8u; ++i)
output[row * 16u + group * 8u + i] = result[i];
#else
// Adapted from realdody/d4r ae530b0: real gfx11 operands/accumulators,
// independent of the shared layout abstraction.
d4r_wmma_h16 a_frag, b_frag;
d4r_wmma_f8 c_frag;
for (unsigned int i = 0; i < 16u; ++i) {
a_frag[i] = a[row * 16u + i];
b_frag[i] = b[row * 16u + i];
}
for (unsigned int i = 0; i < 8u; ++i)
c_frag[i] = initial_c[(2u * i + group) * 16u + row];
d4r_wmma_f8 result = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a_frag, b_frag, c_frag);
if (steps == 2u)
result = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a_frag, b_frag, result);
for (unsigned int i = 0; i < 8u; ++i)
output[(2u * i + group) * 16u + row] = result[i];
#endif
}
// d4r's original gfx11 fragment contract, exercised independently of K/M.