Build native Windows packages for both RDNA4 targets
Add explicit gfx1200/gfx1201 builds, runtime selection and per-target code objects. Guard staging, packaging and installation against mixed architectures; retain gfx1201 compatibility and strict K/M arithmetic. Adapt realdody's target configuration and MSVC binary16/BOOL portability fixes from ae530b0. Do not import its forced gfx12 layout on RDNA3. Add exhaustive binary16 and C++/PowerShell target contract regressions. Validation: 20 CTest gates on RX 9070 XT; four software-only gfx1200 gates; MSVC portability compile checks; exact 4K K async and M control outputs; isolated package install/restore and mixed-target rejection tests. No physical gfx1200 validation is claimed. Co-authored-by: realdody <[email protected]>
This commit is contained in:
1 parent
8f7058d2ba
commit
98de8e3a3e
51 files changed
+636
-127
No files matched your search
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
// Adapted from realdody/d4r ae530b0 (MIT), realdody <[email protected]>.
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace d4r::diag::binary16 {
|
||||
// MSVC has no _Float16 extension. Convert double<->IEEE binary16 explicitly with
|
||||
// round-to-nearest-even, matching a native _Float16 cast. This probe compares the
|
||||
// f16-accumulator MMA against a double sum rounded once to half, so the rounding
|
||||
// must match IEEE 754 binary16 exactly.
|
||||
inline uint16_t half_bits(double value) {
|
||||
uint64_t bits;
|
||||
std::memcpy(&bits, &value, sizeof(bits));
|
||||
const uint16_t sign = static_cast<uint16_t>((bits >> 63) << 15);
|
||||
int32_t exponent = static_cast<int32_t>((bits >> 52) & 0x7ff);
|
||||
uint64_t mantissa = bits & 0x000fffffffffffffULL;
|
||||
if (exponent == 0x7ff) return static_cast<uint16_t>(sign | (mantissa ? 0x7e00 : 0x7c00));
|
||||
if (exponent == 0) return sign; // double subnormal rounds to half zero
|
||||
int32_t unbiased = exponent - 1023;
|
||||
if (unbiased > 15) return static_cast<uint16_t>(sign | 0x7c00);
|
||||
mantissa |= 0x0010000000000000ULL; // implicit leading one (53-bit significand)
|
||||
const int shift = unbiased >= -14 ? 42 : 28 - unbiased;
|
||||
uint64_t rounded = shift >= 64 ? 0 : (mantissa >> shift);
|
||||
if (shift < 64) {
|
||||
const uint64_t remainder = mantissa & ((1ULL << shift) - 1);
|
||||
const uint64_t halfway = 1ULL << (shift - 1);
|
||||
if (remainder > halfway || (remainder == halfway && (rounded & 1))) ++rounded;
|
||||
}
|
||||
if (unbiased >= -14) {
|
||||
if (rounded >= 0x800) { // rounding overflowed into the exponent
|
||||
rounded = 0x400;
|
||||
if (++unbiased > 15) return static_cast<uint16_t>(sign | 0x7c00);
|
||||
}
|
||||
return static_cast<uint16_t>(sign | ((unbiased + 15) << 10) | static_cast<uint16_t>(rounded & 0x3ff));
|
||||
}
|
||||
if (rounded >= 0x400) return static_cast<uint16_t>(sign | 0x0400); // smallest normal half
|
||||
return static_cast<uint16_t>(sign | static_cast<uint16_t>(rounded));
|
||||
}
|
||||
inline double half_value(uint16_t bits) {
|
||||
const bool negative = (bits & 0x8000u) != 0;
|
||||
const uint32_t exponent = (bits >> 10) & 0x1fu;
|
||||
const uint32_t mantissa = bits & 0x3ffu;
|
||||
double magnitude;
|
||||
if (exponent == 0) magnitude = std::ldexp(static_cast<double>(mantissa), -24);
|
||||
else if (exponent == 0x1fu) magnitude = mantissa ? std::numeric_limits<double>::quiet_NaN() : std::numeric_limits<double>::infinity();
|
||||
else magnitude = std::ldexp(static_cast<double>(mantissa) / 1024.0 + 1.0, static_cast<int>(exponent) - 15);
|
||||
return negative ? -magnitude : magnitude;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "binary16.h"
|
||||
#include <cstdio>
|
||||
#include <initializer_list>
|
||||
#include <stdexcept>
|
||||
|
||||
static void check(double value, uint16_t expected) {
|
||||
const auto actual = d4r::diag::binary16::half_bits(value);
|
||||
if (actual != expected) throw std::runtime_error("binary16 rounding mismatch");
|
||||
}
|
||||
int main() {
|
||||
using namespace d4r::diag::binary16;
|
||||
try {
|
||||
unsigned encodings = 0, boundaries = 0;
|
||||
for (unsigned bits = 0; bits < 65536; ++bits) {
|
||||
if ((bits & 0x7c00) == 0x7c00 && (bits & 0x3ff)) continue;
|
||||
check(half_value(uint16_t(bits)), uint16_t(bits));
|
||||
++encodings;
|
||||
}
|
||||
for (unsigned bits = 0; bits < 0x7bff; ++bits) {
|
||||
const double low = half_value(uint16_t(bits)), high = half_value(uint16_t(bits + 1));
|
||||
const double midpoint = (low + high) * 0.5;
|
||||
const uint16_t tie = uint16_t(bits + (bits & 1));
|
||||
check(midpoint, tie); check(-midpoint, uint16_t(tie | 0x8000));
|
||||
check(std::nextafter(midpoint, low), uint16_t(bits));
|
||||
check(std::nextafter(midpoint, high), uint16_t(bits + 1));
|
||||
#if !defined(_MSC_VER)
|
||||
for (double value : {midpoint, -midpoint, std::nextafter(midpoint, low), std::nextafter(midpoint, high)}) {
|
||||
const _Float16 native = static_cast<_Float16>(value);
|
||||
uint16_t expected; std::memcpy(&expected, &native, sizeof(expected));
|
||||
check(value, expected);
|
||||
}
|
||||
#endif
|
||||
++boundaries;
|
||||
}
|
||||
check(65519.0, 0x7bff); check(65520.0, 0x7c00);
|
||||
check(-65520.0, 0xfc00);
|
||||
check(std::numeric_limits<double>::denorm_min(), 0);
|
||||
check(-std::numeric_limits<double>::denorm_min(), 0x8000);
|
||||
check(std::numeric_limits<double>::quiet_NaN(), 0x7e00);
|
||||
std::printf("PASS BINARY16 encodings=%u rounding_boundaries=%u\n", encodings, boundaries);
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::fprintf(stderr, "FAIL BINARY16 %s\n", e.what()); return 5;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Build a private gfx1201 texture override from the user's local DLSS DLL.
|
||||
"""Build a private RDNA4 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.
|
||||
@@ -15,6 +15,14 @@ import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
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]):
|
||||
raise RuntimeError(f'Code object does not target {target}: {path}')
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--dlss-dll', type=pathlib.Path, required=True)
|
||||
@@ -22,6 +30,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('--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)?|'
|
||||
@@ -30,6 +39,8 @@ def main():
|
||||
repo = pathlib.Path(__file__).resolve().parents[2]
|
||||
output = args.output_directory.resolve()
|
||||
output.mkdir(parents=True, exist_ok=True)
|
||||
for existing in output.glob('*.hsaco'):
|
||||
require_code_object_target(existing, args.gpu_arch)
|
||||
work = output / ('work-' + args.kernel)
|
||||
work.mkdir(exist_ok=True)
|
||||
hip = args.hip_root.resolve()
|
||||
@@ -70,7 +81,7 @@ def main():
|
||||
raise RuntimeError('PTX recipe made no changes; refuse a no-op override')
|
||||
raw, ir, extra = work / 'raw.bc', work / 'raw.ll', work / 'extra.bc'
|
||||
run('compile-helper', [tools['clang++'], '-x', 'hip', '-std=c++20', '-nogpuinc', '-nogpulib', '-O3',
|
||||
'-mno-wavefrontsize64', '--offload-device-only', '--offload-arch=gfx1201',
|
||||
'-mno-wavefrontsize64', '--offload-device-only', '--offload-arch=' + args.gpu_arch,
|
||||
'-fgpu-rdc', '-emit-llvm', '-c', '-Xclang', '-fdenormal-fp-math=dynamic',
|
||||
'-DD4R_ACCURACY', '-DD4R_KERNEL_NAME=' + args.kernel,
|
||||
'-o', raw, repo / 'kernels/tex/sust_only.hip'])
|
||||
@@ -79,12 +90,12 @@ def main():
|
||||
for line in ir.read_text().splitlines():
|
||||
if re.search(r'@llvm.used|wchar_size|llvm.module.flags|__hip_cuid', line):
|
||||
continue
|
||||
line = line.replace('optnone', '').replace('"target-cpu"="gfx1201"', '')
|
||||
line = line.replace('optnone', '').replace(f'"target-cpu"="{args.gpu_arch}"', '')
|
||||
lines.append(re.sub(r'"target-features"="[^"]+"', '', line))
|
||||
ir.write_text('\n'.join(lines) + '\n')
|
||||
run('assemble', [tools['llvm-as'], ir, '-o', extra])
|
||||
env['D4R_ZLUDA_EXTRA_BC'] = str(extra)
|
||||
run('emit', [emitter, edited, work / 'emitted', 'gfx1201'])
|
||||
run('emit', [emitter, edited, work / 'emitted', args.gpu_arch])
|
||||
optimized = (work / 'emitted/opt.ll').read_text()
|
||||
definition = re.search(r'^define amdgpu_kernel .*@' + re.escape(args.kernel) + r'\(.*#(\d+)\s*\{', optimized, re.M)
|
||||
if not definition:
|
||||
@@ -93,9 +104,10 @@ def main():
|
||||
expected_mode = '-cumode' if args.shader_mode == 'wgp' else '+cumode'
|
||||
if not attributes or expected_mode not in attributes[1]:
|
||||
raise RuntimeError(f'Emitter did not honor {args.shader_mode} mode; build the corresponding ZLUDA patch first')
|
||||
require_code_object_target(work / 'emitted/module.hsaco', args.gpu_arch)
|
||||
shutil.copyfile(work / 'emitted/module.hsaco', output / (args.kernel + '.hsaco'))
|
||||
run('manifest', [sys.executable, repo / 'kernels/tools/kernel_manifest.py', output, args.dlss_dll])
|
||||
metadata = dict(architecture='gfx1201', accuracy=True, nativeFP8=False, shaderMode=args.shader_mode,
|
||||
metadata = dict(architecture=args.gpu_arch, accuracy=True, nativeFP8=False, shaderMode=args.shader_mode,
|
||||
lastBuiltKernel=args.kernel, lastRecipeRewrites=rewrite_counts,
|
||||
privateNvidiaDerivedCode=True, validation='not yet validated; do not install before comparison',
|
||||
dlssSha256=hashlib.sha256(args.dlss_dll.read_bytes()).hexdigest(),
|
||||
@@ -103,7 +115,7 @@ def main():
|
||||
compiler=subprocess.check_output([str(tools['clang++']), '--version'], env=env).decode(errors='replace'),
|
||||
objects={p.name: hashlib.sha256(p.read_bytes()).hexdigest() for p in output.glob('*.hsaco')})
|
||||
(output / 'build-info.json').write_text(json.dumps(metadata, indent=2) + '\n')
|
||||
print(f'Built PRIVATE gfx1201 texture override: {output}; validation required before use')
|
||||
print(f'Built PRIVATE {args.gpu_arch} texture override: {output}; validation required before use')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -46,7 +46,7 @@ int main(int argc, char** argv)
|
||||
// Require the real HIP architecture, then match the CUDA device by PCI identity.
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(args.device, props);
|
||||
hip.select_architecture(args.device, props);
|
||||
CudaApi api(args.cuda_dll);
|
||||
loaded_modules();
|
||||
std::printf("STAGE cuInit\n");
|
||||
@@ -130,7 +130,7 @@ int main(int argc, char** argv)
|
||||
if (primary) api.check(api.cuDevicePrimaryCtxRelease_v2(device), "cuDevicePrimaryCtxRelease_v2");
|
||||
else api.check(api.cuCtxDestroy_v2(context), "cuCtxDestroy_v2");
|
||||
cleanup.context = nullptr;
|
||||
std::printf("PASS CUDA architecture=gfx1201 context=%s iterations=%u guard_verified=1 queued=%u\n",
|
||||
std::printf("PASS CUDA architecture=%s context=%s iterations=%u guard_verified=1 queued=%u\n", d4r::diag::HipApi::target_arch(),
|
||||
args.context.c_str(), args.iterations, unsigned(queued));
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
|
||||
@@ -8,7 +8,7 @@ int main(int argc, char** argv) {
|
||||
Args args(argc, argv);
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(args.device, props);
|
||||
hip.select_architecture(args.device, props);
|
||||
SearchDirectory search(std::filesystem::path(wide(args.cuda_dll)).parent_path());
|
||||
CudaApi cuda(args.cuda_dll);
|
||||
cuda.check(cuda.cuInit(0), "cuInit");
|
||||
@@ -64,7 +64,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
cuda.check(cuda.cuCtxSynchronize(), "cuCtxSynchronize");
|
||||
std::printf("PASS CUDA_IMAGES architecture=gfx1201 iterations=%u descriptor_and_storage=1 pitched_device_copies=1 fp16_fp32=1 async_array_copy=%u\n",
|
||||
std::printf("PASS CUDA_IMAGES architecture=%s iterations=%u descriptor_and_storage=1 pitched_device_copies=1 fp16_fp32=1 async_array_copy=%u\n", d4r::diag::HipApi::target_arch(),
|
||||
args.iterations, unsigned(std::getenv("D4R_DIAG_ASYNC_ARRAY_COPY") != nullptr));
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "hip_api.h"
|
||||
#include "cuda_api.h"
|
||||
#include "binary16.h"
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
@@ -60,6 +61,10 @@ static constexpr char source[] = R"PTX(
|
||||
}
|
||||
)PTX";
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
using d4r::diag::binary16::half_bits;
|
||||
using d4r::diag::binary16::half_value;
|
||||
#else
|
||||
static uint16_t half_bits(double value) {
|
||||
_Float16 half = static_cast<_Float16>(value);
|
||||
uint16_t bits;
|
||||
@@ -71,6 +76,7 @@ static double half_value(uint16_t bits) {
|
||||
std::memcpy(&half, &bits, sizeof(bits));
|
||||
return static_cast<double>(half);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
using namespace d4r::diag;
|
||||
@@ -79,7 +85,7 @@ int main(int argc, char** argv) {
|
||||
Args args(argc, argv);
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(args.device, props);
|
||||
hip.select_architecture(args.device, props);
|
||||
CudaApi cuda(args.cuda_dll);
|
||||
cuda.check(cuda.cuInit(0), "cuInit");
|
||||
CUdevice device = -1;
|
||||
@@ -155,7 +161,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
std::printf("MMA_REFERENCE cases=%zu elements=%zu differing=%zu\n", cases, d.size(), mismatch);
|
||||
if (mismatch) return 5;
|
||||
std::printf("PASS CUDA_F16_MMA architecture=gfx1201 cases=%zu exact_f16=1\n", cases);
|
||||
std::printf("PASS CUDA_F16_MMA architecture=%s cases=%zu exact_f16=1\n", d4r::diag::HipApi::target_arch(), cases);
|
||||
return 0;
|
||||
} catch (const std::exception& error) {
|
||||
std::fprintf(stderr, "FAIL CUDA_F16_MMA %s\n", error.what());
|
||||
|
||||
@@ -360,9 +360,9 @@ static void STDMETHODCALLTYPE hook_SOSetTargets(ID3D12GraphicsCommandList* self,
|
||||
return original_SOSetTargets(access.target(), start_slot, view_count, views);
|
||||
}
|
||||
|
||||
using Fn_OMSetRenderTargets = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, WINBOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor);
|
||||
using Fn_OMSetRenderTargets = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, BOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor);
|
||||
static Fn_OMSetRenderTargets original_OMSetRenderTargets = nullptr;
|
||||
static void STDMETHODCALLTYPE hook_OMSetRenderTargets(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, WINBOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) {
|
||||
static void STDMETHODCALLTYPE hook_OMSetRenderTargets(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, BOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) {
|
||||
Access access(self);
|
||||
auto saved_render_target_descriptors = copy_values(render_target_descriptors, (single_descriptor_handle ? 1 : render_target_descriptor_count));
|
||||
auto saved_depth_stencil_descriptor = copy_values(depth_stencil_descriptor, 1);
|
||||
|
||||
@@ -123,7 +123,7 @@ int main(int argc, char** argv) {
|
||||
std::unique_ptr<HipApi> hip;
|
||||
hipDeviceProp_t props{};
|
||||
const bool no_hip = std::getenv("D4R_COMMAND_PROBE_NO_HIP") != nullptr;
|
||||
if (!no_hip) { hip = std::make_unique<HipApi>(args.hip_root); hip->select_gfx1201(args.device, props); }
|
||||
if (!no_hip) { hip = std::make_unique<HipApi>(args.hip_root); hip->select_architecture(args.device, props); }
|
||||
ComPtr<IDXGIFactory4> factory; dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "Probe DXGI");
|
||||
ComPtr<IDXGIAdapter1> adapter;
|
||||
for (UINT i = 0; ; ++i) {
|
||||
@@ -295,7 +295,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
const bool warp = std::getenv("D4R_COMMAND_PROBE_WARP") != nullptr;
|
||||
std::printf("PASS D3D12_COMMAND_BACKEND adapter=%s architecture=%s backend=%u iterations=%u batch_order=1 root_state=1 deep_copy=1 indirect=%u indirect_reset=%u reset_reuse=%u live_recordings=0 frame_age=0\n",
|
||||
warp ? "WARP" : "AMD", warp ? "software" : no_hip ? "not_queried" : "gfx1201", !no_hooks,
|
||||
warp ? "WARP" : "AMD", warp ? "software" : no_hip ? "not_queried" : HipApi::target_arch(), !no_hooks,
|
||||
args.iterations, indirect_enabled, root_indirect, no_hooks ? 0 : 2 * args.iterations);
|
||||
return 0;
|
||||
} catch (const std::exception& failure) {
|
||||
|
||||
@@ -30,7 +30,7 @@ int main(int argc, char** argv) {
|
||||
std::make_pair("D4R_NVCUDA_DLL", args.cuda_dll), std::make_pair("D4R_NVAPI_DLL", args.nvapi_dll),
|
||||
std::make_pair("D4R_NGX_CORE", args.ngx_core), std::make_pair("D4R_DLSS_DLL", args.dlss_dll)})
|
||||
if (_putenv_s(pair.first, pair.second.c_str())) throw std::runtime_error("Cannot set runtime environment");
|
||||
HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_gfx1201(args.device, props);
|
||||
HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_architecture(args.device, props);
|
||||
ComPtr<IDXGIFactory4> factory; dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "CreateDXGIFactory1");
|
||||
ComPtr<IDXGIAdapter1> adapter;
|
||||
bool found = false;
|
||||
@@ -169,7 +169,7 @@ int main(int argc, char** argv) {
|
||||
if (!matches) throw std::runtime_error("Imported D3D12 VRAM to CUDA array mismatch on plane " + std::to_string(i));
|
||||
timeline.drain(queue.Get());
|
||||
}
|
||||
std::printf("PASS D3D12_ARRAY_COPY architecture=gfx1201 planes=5 cpu_copies_between_apis=0\n");
|
||||
std::printf("PASS D3D12_ARRAY_COPY architecture=%s planes=5 cpu_copies_between_apis=0\n", d4r::diag::HipApi::target_arch());
|
||||
return 0;
|
||||
}
|
||||
Library shim(wide(args.module));
|
||||
@@ -398,7 +398,7 @@ int main(int argc, char** argv) {
|
||||
std::printf("D4R_BURST_VALIDATION frames=%zu cpu_readback_after_all_submissions=1\n", submitted.size());
|
||||
}
|
||||
loaded_modules();
|
||||
std::printf("PASS D3D12_DLSS architecture=gfx1201 preset=%u frames=%u fast_path_cpu_copies=0 frame_age=0 enhanced=%u queue_integration=%s\n",
|
||||
std::printf("PASS D3D12_DLSS architecture=%s preset=%u frames=%u fast_path_cpu_copies=0 frame_age=0 enhanced=%u queue_integration=%s\n", d4r::diag::HipApi::target_arch(),
|
||||
args.preset, args.iterations, enhanced, commandBackend ? "recorded_command_list" : "explicit_harness");
|
||||
return 0;
|
||||
} catch (const std::exception& error) { std::fprintf(stderr, "FAIL D3D12_DLSS %s\n", error.what()); loaded_modules(); return 4; }
|
||||
|
||||
@@ -137,7 +137,7 @@ int main(int argc, char** argv)
|
||||
throw std::runtime_error("--stream-lifetime must be persistent or cycle");
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(args.device, props);
|
||||
hip.select_architecture(args.device, props);
|
||||
ExternalApi external{hip};
|
||||
ComPtr<IDXGIFactory4> factory;
|
||||
dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "CreateDXGIFactory1");
|
||||
@@ -336,7 +336,7 @@ int main(int argc, char** argv)
|
||||
DWORD handles_after = 0; GetProcessHandleCount(GetCurrentProcess(), &handles_after);
|
||||
std::printf("HANDLES before=%lu after=%lu\n", handles_before, handles_after);
|
||||
if (final_cycle_handles > warmed_handles + 4) throw std::runtime_error("Handle count grew after first-cycle warmup");
|
||||
std::printf("PASS INTEROP architecture=gfx1201 iterations=%u texture=R32_UINT external_fence=1\n", args.iterations);
|
||||
std::printf("PASS INTEROP architecture=%s iterations=%u texture=R32_UINT external_fence=1\n", d4r::diag::HipApi::target_arch(), args.iterations);
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::fprintf(stderr, "FAIL INTEROP %s\n", e.what());
|
||||
|
||||
@@ -170,7 +170,7 @@ std::vector<uint32_t> read_reference(ID3D12Device* device, ID3D12CommandQueue* q
|
||||
int main(int argc, char** argv) {
|
||||
start();
|
||||
try {
|
||||
Args args(argc, argv); HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_gfx1201(args.device, props);
|
||||
Args args(argc, argv); HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_architecture(args.device, props);
|
||||
ExternalApi external{hip}; PixelProgram program(hip, wide(args.module));
|
||||
{
|
||||
PixelAllocation diagnostic(hip,3,1,8);
|
||||
@@ -259,6 +259,6 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
++verified; std::printf("PASS PIXEL_FORMAT name=%s plane=%u pixels=%u decode_max_abs=%.9g encode=%u\n", item.name,item.plane,count,maxAbs,item.plane==0);
|
||||
}
|
||||
std::printf("PASS D3D12_GPU_FORMATS architecture=gfx1201 cases=%u iterations=%u width=%u height=%u enhanced=%u typed_srv_reference=1 typed_uav_reference=1\n", verified,args.iterations,width,height,enhanced); return 0;
|
||||
std::printf("PASS D3D12_GPU_FORMATS architecture=%s cases=%u iterations=%u width=%u height=%u enhanced=%u typed_srv_reference=1 typed_uav_reference=1\n", d4r::diag::HipApi::target_arch(), verified,args.iterations,width,height,enhanced); return 0;
|
||||
} catch (const std::exception& error) { std::fprintf(stderr,"FAIL D3D12_GPU_FORMATS %s\n",error.what()); loaded_modules(); return 1; }
|
||||
}
|
||||
@@ -87,10 +87,10 @@ 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_gfx1201(-1,props);
|
||||
d4r::diag::HipApi hip(d4r::win::env_path("D4R_HIP_ROOT")); hipDeviceProp_t props{}; hip.select_architecture(-1,props);
|
||||
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=gfx1201\n",info->FeatureID,requirements->FeatureSupported);
|
||||
std::printf("D4R_REQUIREMENTS feature=%u support=%u architecture=%s\n",info->FeatureID,requirements->FeatureSupported,d4r::diag::HipApi::target_arch());
|
||||
return 1u;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -52,8 +52,9 @@ def generate(source):
|
||||
slot = 9 # IUnknown(3), ID3D12Object(4), DeviceChild(1), CommandList(1).
|
||||
for version, interface, methods in sorted(classes):
|
||||
for result, name, arguments in methods:
|
||||
result = ' '.join(result.split())
|
||||
arguments = ' '.join(arguments.split())
|
||||
# MinGW WINBOOL and Microsoft SDK BOOL have the same ABI.
|
||||
result = ' '.join(result.split()).replace('WINBOOL', 'BOOL')
|
||||
arguments = ' '.join(arguments.split()).replace('WINBOOL', 'BOOL')
|
||||
declarations = [arg.strip() for arg in arguments.split(',')] if arguments else []
|
||||
names = []
|
||||
for declaration in declarations:
|
||||
|
||||
@@ -30,7 +30,7 @@ int main(int argc, char** argv)
|
||||
if (args.module.empty()) throw std::runtime_error("--module is required");
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t properties{};
|
||||
hip.select_gfx1201(args.device, properties);
|
||||
hip.select_architecture(args.device, properties);
|
||||
hipModule_t module = nullptr;
|
||||
hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(WMMA)");
|
||||
struct ModuleCleanup {
|
||||
@@ -120,7 +120,7 @@ int main(int argc, char** argv)
|
||||
}
|
||||
}
|
||||
}
|
||||
std::printf("PASS GFX12_WMMA architecture=gfx1201 modes=raw,legacy_adapter,upstream_layout iterations=%u max_abs=%.9g max_rel=%.9g\n",
|
||||
std::printf("PASS GFX12_WMMA architecture=%s modes=raw,legacy_adapter,upstream_layout iterations=%u max_abs=%.9g max_rel=%.9g\n", d4r::diag::HipApi::target_arch(),
|
||||
args.iterations, max_absolute_error, max_relative_error);
|
||||
return 0;
|
||||
} catch (const std::exception& error) {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"architecture": "@D4R_GPU_ARCH@",
|
||||
"wavefrontSize": 32,
|
||||
"validation": "Compilation is not hardware validation; run the GPU diagnostics."
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#ifndef D4R_TARGET_ARCH
|
||||
#define D4R_TARGET_ARCH "gfx1201"
|
||||
#endif
|
||||
|
||||
namespace d4r::diag {
|
||||
inline bool supported_gpu_target(const std::string& target) {
|
||||
return target == "gfx1200" || target == "gfx1201";
|
||||
}
|
||||
inline std::string gpu_architecture(const std::string& name) {
|
||||
return name.substr(0, name.find(':'));
|
||||
}
|
||||
inline void require_gpu_target(const std::string& actual, const std::string& expected) {
|
||||
if (!supported_gpu_target(expected) || gpu_architecture(actual) != expected)
|
||||
throw std::runtime_error("GPU architecture mismatch: detected " + actual + ", package requires " + expected);
|
||||
}
|
||||
inline std::string code_object_target(const std::filesystem::path& path) {
|
||||
// AMDGPU ELF e_flags machine IDs from LLVM's documented code-object ABI.
|
||||
// Never infer compatibility from a filename or rewrite the ELF target.
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
std::array<unsigned char, 64> header{};
|
||||
if (!file.read(reinterpret_cast<char*>(header.data()), header.size()) ||
|
||||
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());
|
||||
}
|
||||
}
|
||||
inline void require_code_object_target(const std::filesystem::path& path, const std::string& expected) {
|
||||
require_gpu_target(code_object_target(path), expected);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "gpu_target.h"
|
||||
#include <cstdio>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
using namespace d4r::diag;
|
||||
try {
|
||||
unsigned rejected = 0, objects = 0;
|
||||
for (const char* target : {"gfx1200", "gfx1201"}) {
|
||||
require_gpu_target(target, target);
|
||||
require_gpu_target(std::string(target) + ":xnack-:sramecc-", target);
|
||||
for (const char* invalid : {"gfx1101", "gfx12000", "gfx1202", "gfx1250", ""}) {
|
||||
try { require_gpu_target(invalid, target); }
|
||||
catch (const std::exception&) { ++rejected; continue; }
|
||||
throw std::runtime_error("Invalid GPU target accepted");
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
require_code_object_target(argv[i], D4R_TARGET_ARCH);
|
||||
const auto other = std::string(D4R_TARGET_ARCH) == "gfx1201" ? "gfx1200" : "gfx1201";
|
||||
try { require_code_object_target(argv[i], other); }
|
||||
catch (const std::exception&) { ++rejected; ++objects; continue; }
|
||||
throw std::runtime_error("Wrong code-object target accepted");
|
||||
}
|
||||
if (!objects) throw std::runtime_error("Supply actual compiled code objects");
|
||||
std::printf("PASS GPU_TARGET_CONTRACT target=%s objects=%u rejected=%u hardware_executed=0\n",
|
||||
D4R_TARGET_ARCH, objects, rejected);
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::fprintf(stderr, "FAIL GPU_TARGET_CONTRACT %s\n", e.what()); return 5;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "diagnostic.h"
|
||||
#include "gpu_target.h"
|
||||
#include <hip/hip_runtime_api.h>
|
||||
|
||||
namespace d4r::diag {
|
||||
@@ -40,7 +41,8 @@ struct HipApi {
|
||||
if (verbose || result != hipSuccess) std::printf("HIP %s -> %d (%s)\n", call, static_cast<int>(result), hipGetErrorName(result));
|
||||
if (result != hipSuccess) throw std::runtime_error(std::string(call) + ": " + hipGetErrorString(result));
|
||||
}
|
||||
int select_gfx1201(int requested, hipDeviceProp_t& selected) const {
|
||||
static const char* target_arch() { return D4R_TARGET_ARCH; }
|
||||
int select_architecture(int requested, hipDeviceProp_t& selected) 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);
|
||||
@@ -59,14 +61,16 @@ struct HipApi {
|
||||
i, props.name, props.gcnArchName, props.warpSize, props.totalGlobalMem,
|
||||
props.pciDomainID, props.pciBusID, props.pciDeviceID);
|
||||
const std::string arch = props.gcnArchName;
|
||||
if (arch.substr(0, arch.find(':')) == "gfx1201" && (requested < 0 || requested == i) && found < 0) {
|
||||
if (gpu_architecture(arch) == target_arch() && (requested < 0 || requested == i) && found < 0) {
|
||||
found = i;
|
||||
selected = props;
|
||||
}
|
||||
}
|
||||
if (found < 0) throw std::runtime_error("No selected gfx1201 device; never substitute gfx110x");
|
||||
if (found < 0) throw std::runtime_error(std::string("No selected ") + target_arch() + " device; refusing architecture substitution");
|
||||
require_gpu_target(selected.gcnArchName, target_arch());
|
||||
check(hipSetDevice(found), "hipSetDevice");
|
||||
std::printf("SELECTED HIP ordinal=%d architecture=gfx1201\n", found);
|
||||
std::printf("SELECTED HIP ordinal=%d architecture=%s validation=%s\n", found, target_arch(),
|
||||
std::string(target_arch()) == "gfx1201" ? "previously_tested_target" : "hardware_unverified_target");
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,13 +9,13 @@ int main(int argc, char** argv)
|
||||
if (args.module.empty()) throw std::runtime_error("--module is required");
|
||||
HipApi api(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
api.select_gfx1201(args.device, props);
|
||||
api.select_architecture(args.device, props);
|
||||
loaded_modules();
|
||||
size_t free = 0, total = 0;
|
||||
api.check(api.hipMemGetInfo(&free, &total), "hipMemGetInfo");
|
||||
std::printf("VRAM free=%zu total=%zu\n", free, total);
|
||||
hipModule_t module = nullptr;
|
||||
api.check(api.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(gfx1201)");
|
||||
api.check(api.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(target)");
|
||||
struct ModuleCleanup { HipApi& api; hipModule_t m; ~ModuleCleanup() { if (m) (void)api.hipModuleUnload(m); } } cleanup{api, module};
|
||||
hipFunction_t kernel = nullptr;
|
||||
api.check(api.hipModuleGetFunction(&kernel, module, "d4r_probe_pattern"), "hipModuleGetFunction");
|
||||
@@ -41,7 +41,7 @@ int main(int argc, char** argv)
|
||||
allocation_cleanup.p = nullptr;
|
||||
api.check(api.hipModuleUnload(module), "hipModuleUnload");
|
||||
cleanup.m = nullptr;
|
||||
std::printf("PASS HIP architecture=gfx1201 iterations=%u guard_verified=1\n", args.iterations);
|
||||
std::printf("PASS HIP architecture=%s iterations=%u guard_verified=1\n", d4r::diag::HipApi::target_arch(), args.iterations);
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::fprintf(stderr, "FAIL HIP %s\n", e.what());
|
||||
|
||||
@@ -9,7 +9,7 @@ int main(int argc, char** argv)
|
||||
Args args(argc, argv);
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(args.device, props);
|
||||
hip.select_architecture(args.device, props);
|
||||
hipModule_t module = nullptr;
|
||||
hipFunction_t kernel = nullptr;
|
||||
void* output = nullptr;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compare real gfx1201 K enc1/enc2 launches with the existing numpy reference."""
|
||||
"""Compare RDNA4 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 architecture=gfx1201 kernel={args.kernel_name} "
|
||||
print(f"PASS K_REFERENCE reference_layout=gfx12 kernel={args.kernel_name} "
|
||||
"nonzero_weights=1 transformer_executed=1 nan_inf=0")
|
||||
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ int main(int argc, char** argv)
|
||||
if (args.module.empty()) throw std::runtime_error("--module is required");
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t properties{};
|
||||
hip.select_gfx1201(args.device, properties);
|
||||
hip.select_architecture(args.device, properties);
|
||||
if (args.kernel_name != "enc1" && args.kernel_name != "enc2")
|
||||
throw std::runtime_error("--kernel-name must be enc1 or enc2");
|
||||
const bool enc2 = args.kernel_name == "enc2";
|
||||
@@ -124,7 +124,7 @@ int main(int argc, char** argv)
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
std::printf("PASS K_IDENTITY architecture=gfx1201 kernel=%s iterations=%u full_elements=%zu merged_elements=%zu transformer_executed=1 nonzero_weights=0\n",
|
||||
std::printf("PASS K_IDENTITY architecture=%s kernel=%s iterations=%u full_elements=%zu merged_elements=%zu transformer_executed=1 nonzero_weights=0\n", d4r::diag::HipApi::target_arch(),
|
||||
args.kernel_name.c_str(), args.iterations, full_elements, merged_elements);
|
||||
|
||||
// Exercise nonzero V projection, position-only attention and Wo GEMMs.
|
||||
@@ -213,7 +213,7 @@ int main(int argc, char** argv)
|
||||
save("full.bin", full.data(), full.size() * sizeof(uint16_t));
|
||||
save("merged.bin", merged.data(), merged.size() * sizeof(uint16_t));
|
||||
}
|
||||
std::printf("PASS K_NONZERO architecture=gfx1201 kernel=%s changed_elements=%zu full_elements=%zu merged_elements=%zu fixture_saved=%d numerical_reference_pending=1\n",
|
||||
std::printf("PASS K_NONZERO architecture=%s kernel=%s changed_elements=%zu full_elements=%zu merged_elements=%zu fixture_saved=%d numerical_reference_pending=1\n", d4r::diag::HipApi::target_arch(),
|
||||
args.kernel_name.c_str(), changed, full.size(), merged.size(), !args.fixture_dir.empty());
|
||||
return 0;
|
||||
} catch (const std::exception& error) {
|
||||
|
||||
@@ -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} architecture=gfx1201 nan_inf=0')
|
||||
print(f'PASS K_REPLAY_REFERENCE kernel={layer} reference_layout=gfx12 nan_inf=0')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -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)} architecture=gfx1201 nan_inf=0')
|
||||
print(f'PASS M_REPLAY_REFERENCE kernel={layer} blocks={len(pairs)} reference_layout=gfx12 nan_inf=0')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -37,7 +37,7 @@ int main(int argc, char** argv) {
|
||||
throw std::runtime_error("--module, --fixture-dir and --output-dir are required");
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(args.device, props);
|
||||
hip.select_architecture(args.device, props);
|
||||
const std::filesystem::path input(wide(args.fixture_dir)), output(wide(args.output_dir));
|
||||
auto parameters = read_file(input / L"args.bin");
|
||||
if (parameters.empty() || parameters.size() > 4096) throw std::runtime_error("Invalid replay parameter size");
|
||||
@@ -84,7 +84,7 @@ int main(int argc, char** argv) {
|
||||
std::memcpy(parameters.data() + offset, &pointer, 8);
|
||||
}
|
||||
hipModule_t module = nullptr;
|
||||
hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(replay gfx1201)");
|
||||
hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(replay)");
|
||||
struct Cleanup { HipApi& hip; hipModule_t module; ~Cleanup() { (void)hip.hipModuleUnload(module); } } cleanup{hip, module};
|
||||
if (const char* debugBlock = std::getenv("D4R_SWIN_DEBUG_BLOCK")) {
|
||||
int coordinates[2]{};
|
||||
@@ -240,7 +240,7 @@ int main(int argc, char** argv) {
|
||||
file.write(reinterpret_cast<const char*>(bytes.data()), std::streamsize(bytes.size()));
|
||||
if (!file) throw std::runtime_error("Cannot save replay allocation");
|
||||
}
|
||||
std::printf("PASS NATIVE_REPLAY architecture=gfx1201 kernel=%s iterations=%u benchmark_pairs=%u numerical_reference=pending\n",
|
||||
std::printf("PASS NATIVE_REPLAY architecture=%s kernel=%s iterations=%u benchmark_pairs=%u numerical_reference=pending\n", d4r::diag::HipApi::target_arch(),
|
||||
kernel.c_str(), args.benchmark_module.empty() ? args.iterations : 1, args.benchmark_module.empty() ? 0 : args.iterations);
|
||||
return 0;
|
||||
} catch (const std::exception& error) {
|
||||
|
||||
@@ -34,7 +34,7 @@ int main(int argc, char** argv)
|
||||
if (dlss_path.filename() != L"nvngx_dlss.dll") throw std::runtime_error("DLSS file must be named nvngx_dlss.dll");
|
||||
HipApi hip(args.hip_root);
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(args.device, props);
|
||||
hip.select_architecture(args.device, props);
|
||||
SearchDirectory cuda_search(std::filesystem::path(wide(args.cuda_dll)).parent_path());
|
||||
CudaApi cuda(args.cuda_dll);
|
||||
cuda.check(cuda.cuInit(0), "cuInit");
|
||||
@@ -124,7 +124,7 @@ int main(int argc, char** argv)
|
||||
cuda.check(cuda.cuCtxSynchronize(), "cuCtxSynchronize");
|
||||
cuda.check(cuda.cuCtxSetCurrent(nullptr), "cuCtxSetCurrent(NULL)");
|
||||
cuda.check(cuda.cuDevicePrimaryCtxRelease_v2(device), "cuDevicePrimaryCtxRelease_v2"); context = nullptr;
|
||||
std::printf("PASS NGX_INIT architecture=gfx1201 sr_available=1 transformer_validation=pending\n");
|
||||
std::printf("PASS NGX_INIT architecture=%s sr_available=1 transformer_validation=pending\n", d4r::diag::HipApi::target_arch());
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
std::fprintf(stderr, "FAIL NGX_INIT %s\n", e.what());
|
||||
|
||||
@@ -42,7 +42,7 @@ inline std::filesystem::path pixel_module_path() {
|
||||
reinterpret_cast<LPCWSTR>(&pixel_module_path), &module)) throw std::runtime_error("Locate GPU conversion module directory");
|
||||
wchar_t path[32768]{}; const DWORD length = GetModuleFileNameW(module, path, 32768);
|
||||
if (!length || length == 32768) throw std::runtime_error("GPU conversion module path is invalid");
|
||||
return std::filesystem::path(path).parent_path() / L"pixel_convert_gfx1201.hsaco";
|
||||
return std::filesystem::path(path).parent_path() / diag::wide(std::string("pixel_convert_") + diag::HipApi::target_arch() + ".hsaco");
|
||||
}
|
||||
|
||||
struct Runtime {
|
||||
@@ -94,7 +94,7 @@ struct Runtime {
|
||||
if (!d3d) throw std::runtime_error("Null D3D12 device");
|
||||
try {
|
||||
hipDeviceProp_t props{};
|
||||
hip.select_gfx1201(-1, props);
|
||||
hip.select_architecture(-1, props);
|
||||
hip.verbose = cuda.verbose = !std::getenv("D4R_QUIET_API");
|
||||
const auto luid = adapter_luid(d3d);
|
||||
if (std::memcmp(&luid, props.luid, sizeof(luid))) throw std::runtime_error("D3D12/HIP LUID mismatch");
|
||||
@@ -155,7 +155,7 @@ struct Runtime {
|
||||
ngx_check(destroy(caps), "Destroy capability parameters");
|
||||
if (available != 1 || initResult != 1 || needsDriver != 0)
|
||||
throw std::runtime_error("CUDA DLSS is unavailable after capability initialization");
|
||||
std::printf("D4R_RUNTIME platform=Windows architecture=gfx1201 cpu_frame_copies=0 frame_age=0\n");
|
||||
std::printf("D4R_RUNTIME platform=Windows architecture=%s cpu_frame_copies=0 frame_age=0\n", d4r::diag::HipApi::target_arch());
|
||||
} catch (...) { cleanup(); throw; }
|
||||
}
|
||||
Runtime(const Runtime&) = delete;
|
||||
|
||||
@@ -27,11 +27,11 @@ int __cdecl initialize()
|
||||
const char* root = std::getenv("HIP_PATH");
|
||||
if (!root) return -5;
|
||||
auto runtime = std::make_unique<d4r::diag::HipApi>(root);
|
||||
device_ordinal = runtime->select_gfx1201(-1, properties);
|
||||
device_ordinal = runtime->select_architecture(-1, properties);
|
||||
hip = std::move(runtime);
|
||||
runtime_ready.store(true, std::memory_order_release);
|
||||
}
|
||||
std::printf("NVAPI_COMPAT initialize physical=gfx1201 CUDA_model_profile=AD100\n");
|
||||
std::printf("NVAPI_COMPAT initialize physical=%s CUDA_model_profile=AD100\n", properties.gcnArchName);
|
||||
return 0;
|
||||
} catch (const std::exception& e) { std::fprintf(stderr, "NVAPI_COMPAT init failed: %s\n", e.what()); return -1; }
|
||||
}
|
||||
@@ -48,7 +48,7 @@ int __cdecl architecture(void* handle, ArchInfo* info)
|
||||
if (!valid(handle) || !info) return -5;
|
||||
if (info->version != (sizeof(ArchInfo) | 1u << 16) && info->version != (sizeof(ArchInfo) | 2u << 16)) return -9;
|
||||
info->architecture = 0x190; info->implementation = 2; info->revision = 0x11;
|
||||
std::printf("NVAPI_COMPAT GetArchInfo profile=AD102 physical=gfx1201\n");
|
||||
std::printf("NVAPI_COMPAT GetArchInfo profile=AD102 physical=%s\n", properties.gcnArchName);
|
||||
return 0;
|
||||
}
|
||||
int __cdecl adapter_id(void* handle, void* luid)
|
||||
|
||||
@@ -58,6 +58,7 @@ class PixelProgram {
|
||||
public:
|
||||
PixelProgram(diag::HipApi& hip, const std::filesystem::path& module) : hip_(hip) {
|
||||
try {
|
||||
diag::require_code_object_target(module, diag::HipApi::target_arch());
|
||||
hip.check(hip.hipModuleLoad(&module_, diag::utf8(module.c_str()).c_str()), "Load native GPU format conversion");
|
||||
hip.check(hip.hipModuleGetFunction(&decode_, module_, "d4r_pixel_decode"), "Resolve GPU pixel decode");
|
||||
hip.check(hip.hipModuleGetFunction(&encode_, module_, "d4r_pixel_encode"), "Resolve GPU pixel encode");
|
||||
|
||||
Reference in new issue
Block a user