Add native K/M/RR inference engines, HIP kernels, replay and validation harnesses, and Windows DLSS setup and runtime support. Include GPU profiling tools, build and packaging scripts, platform integration patches, and implementation documentation.
135 lines
8.7 KiB
C++
135 lines
8.7 KiB
C++
#include "hip_api.h"
|
|
#include "cuda_api.h"
|
|
#include "ngx_cuda_evaluate.h"
|
|
|
|
// Same NGX C ABI and freestanding MSVC parameter accessors as the upstream shim.
|
|
// NVIDIA SDK headers and proprietary binaries are not build dependencies.
|
|
struct NgxPathListInfo { const wchar_t* const* Path; unsigned Length; };
|
|
struct NgxLoggingInfo { void* LoggingCallback; int MinimumLoggingLevel; bool DisableOtherLoggingSinks; };
|
|
struct NgxFeatureCommonInfo { NgxPathListInfo PathListInfo; void* InternalData; NgxLoggingInfo LoggingInfo; };
|
|
static_assert(sizeof(NgxFeatureCommonInfo) == 40);
|
|
extern "C" void d4r_ngx_set_uint(void*, const char*, unsigned);
|
|
extern "C" unsigned d4r_ngx_get_uint(void*, const char*, unsigned*);
|
|
extern "C" unsigned d4r_ngx_get_int(void*, const char*, int*);
|
|
|
|
static void ngx_log(const char* message, int level, unsigned component)
|
|
{
|
|
if (message) std::printf("NGX_LOG level=%d component=%u %s\n", level, component, message);
|
|
}
|
|
static void check(unsigned result, const char* call)
|
|
{
|
|
std::printf("NGX %s -> 0x%08x\n", call, result);
|
|
if (result != 1) throw std::runtime_error(std::string(call) + " NGX result=" + std::to_string(result));
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
using namespace d4r::diag;
|
|
start();
|
|
try {
|
|
Args args(argc, argv);
|
|
if (args.cuda_dll.empty() || args.ngx_core.empty() || args.dlss_dll.empty())
|
|
throw std::runtime_error("--cuda-dll, --ngx-core and --dlss-dll absolute paths required");
|
|
const std::filesystem::path core_path(wide(args.ngx_core)), dlss_path(wide(args.dlss_dll));
|
|
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_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");
|
|
int count = 0;
|
|
cuda.check(cuda.cuDeviceGetCount(&count), "cuDeviceGetCount");
|
|
CUdevice device = -1;
|
|
for (int i = 0; i < count; ++i) {
|
|
CUdevice candidate = -1;
|
|
int bus = -1, pci_device = -1, domain = -1;
|
|
cuda.check(cuda.cuDeviceGet(&candidate, i), "cuDeviceGet");
|
|
cuda.check(cuda.cuDeviceGetAttribute(&bus, 33, candidate), "cuDeviceGetAttribute(PCI_BUS_ID)");
|
|
cuda.check(cuda.cuDeviceGetAttribute(&pci_device, 34, candidate), "cuDeviceGetAttribute(PCI_DEVICE_ID)");
|
|
cuda.check(cuda.cuDeviceGetAttribute(&domain, 50, candidate), "cuDeviceGetAttribute(PCI_DOMAIN_ID)");
|
|
if (bus == props.pciBusID && pci_device == props.pciDeviceID && domain == props.pciDomainID) device = candidate;
|
|
}
|
|
if (device < 0) throw std::runtime_error("NGX CUDA/HIP PCI identity mismatch");
|
|
CUcontext context = nullptr;
|
|
cuda.check(cuda.cuDevicePrimaryCtxRetain(&context, device), "cuDevicePrimaryCtxRetain");
|
|
struct ContextCleanup {
|
|
CudaApi& cuda; CUcontext& context; CUdevice device;
|
|
~ContextCleanup() { if (context) { (void)cuda.cuCtxSetCurrent(nullptr); (void)cuda.cuDevicePrimaryCtxRelease_v2(device); } }
|
|
} cc{cuda, context, device};
|
|
cuda.check(cuda.cuCtxSetCurrent(context), "cuCtxSetCurrent");
|
|
auto nvapi_path = std::filesystem::path(wide(args.cuda_dll)).parent_path() / L"nvapi64.dll";
|
|
if (!std::filesystem::exists(nvapi_path)) nvapi_path = nvapi_path.parent_path().parent_path() / L"nvapi64.dll";
|
|
if (!args.nvapi_dll.empty()) nvapi_path = wide(args.nvapi_dll);
|
|
Library nvapi(nvapi_path);
|
|
SearchDirectory feature_search(dlss_path.parent_path());
|
|
// Preload the supplied absolute file so a system copy cannot replace it.
|
|
Library dlss(dlss_path), core(core_path);
|
|
using Init = unsigned(*)(unsigned long long, const wchar_t*, const NgxFeatureCommonInfo*, unsigned);
|
|
using ProjectInit = unsigned(*)(const char*, int, const char*, const wchar_t*, unsigned, const NgxFeatureCommonInfo*);
|
|
using Shutdown = unsigned(*)();
|
|
using Parameters = unsigned(*)(void**);
|
|
using Destroy = unsigned(*)(void*);
|
|
const auto init = core.symbol<Init>("NVSDK_NGX_CUDA_Init");
|
|
const auto shutdown = core.symbol<Shutdown>("NVSDK_NGX_CUDA_Shutdown");
|
|
const auto capabilities = core.symbol<Parameters>("NVSDK_NGX_CUDA_GetCapabilityParameters");
|
|
const auto allocate = core.symbol<Parameters>("NVSDK_NGX_CUDA_AllocateParameters");
|
|
const auto destroy = core.symbol<Destroy>("NVSDK_NGX_CUDA_DestroyParameters");
|
|
const std::wstring directory = dlss_path.parent_path().wstring();
|
|
const wchar_t* paths[] = {directory.c_str()};
|
|
const char* diagnostic_dir = std::getenv("D4R_DIAG_DIR");
|
|
const auto data_path = diagnostic_dir ? std::filesystem::path(wide(diagnostic_dir)) :
|
|
std::filesystem::current_path() / L"test-results" / L"ngx-init";
|
|
std::filesystem::create_directories(data_path);
|
|
NgxFeatureCommonInfo common{};
|
|
common.PathListInfo = {paths, 1};
|
|
common.LoggingInfo = {reinterpret_cast<void*>(&ngx_log), 2, false};
|
|
loaded_modules();
|
|
std::printf("STAGE NVSDK_NGX_CUDA_Init sdk=0x15 core=%s dlss=%s\n", args.ngx_core.c_str(), args.dlss_dll.c_str());
|
|
std::printf("NGX_APPLICATION id=%llu\n", args.ngx_app_id);
|
|
if (args.ngx_abi == "driver" || args.ngx_abi == "sdk")
|
|
check(init(args.ngx_app_id, data_path.c_str(), &common, 0x15), "NVSDK_NGX_CUDA_Init(application ABI)");
|
|
else if (args.ngx_abi == "project") check(core.symbol<ProjectInit>("NVSDK_NGX_CUDA_Init_ProjectID")(
|
|
args.ngx_project_id.c_str(), args.ngx_project_engine, args.ngx_project_version.c_str(),
|
|
data_path.c_str(), 0x15, &common), "NVSDK_NGX_CUDA_Init_ProjectID");
|
|
else throw std::runtime_error("--ngx-abi must be driver, sdk or project");
|
|
bool initialized = true;
|
|
struct NgxCleanup { Shutdown shutdown; bool& active; ~NgxCleanup() { if (active) (void)shutdown(); } } nc{shutdown, initialized};
|
|
void* caps = nullptr;
|
|
check(capabilities(&caps), "NVSDK_NGX_CUDA_GetCapabilityParameters");
|
|
if (!caps) throw std::runtime_error("NGX returned null capability parameters");
|
|
struct ParameterCleanup { Destroy destroy; void*& p; ~ParameterCleanup() { if (p) (void)destroy(p); } } pc{destroy, caps};
|
|
int available = -1, init_result = -1, needs_driver = -1;
|
|
check(d4r_ngx_get_int(caps, "SuperSampling.Available", &available), "Get(SuperSampling.Available)");
|
|
check(d4r_ngx_get_int(caps, "SuperSampling.FeatureInitResult", &init_result), "Get(SuperSampling.FeatureInitResult)");
|
|
check(d4r_ngx_get_int(caps, "SuperSampling.NeedsUpdatedDriver", &needs_driver), "Get(SuperSampling.NeedsUpdatedDriver)");
|
|
std::printf("CAPABILITIES available=%d feature_init=0x%08x needs_driver=%d\n", available, static_cast<unsigned>(init_result), needs_driver);
|
|
if (available != 1 || init_result != 1 || needs_driver != 0)
|
|
throw std::runtime_error("DLSS CUDA feature is unavailable; initialization alone is insufficient");
|
|
void* parameters = nullptr;
|
|
check(allocate(¶meters), "NVSDK_NGX_CUDA_AllocateParameters");
|
|
if (!parameters) throw std::runtime_error("Null NGX parameters");
|
|
ParameterCleanup ac{destroy, parameters};
|
|
d4r_ngx_set_uint(parameters, "Width", 640);
|
|
unsigned roundtrip = 0;
|
|
check(d4r_ngx_get_uint(parameters, "Width", &roundtrip), "MSVC parameter ABI roundtrip");
|
|
if (roundtrip != 640) throw std::runtime_error("NGX parameter ABI mismatch");
|
|
if (args.ngx_mode == "evaluate")
|
|
run_synthetic_dlss(cuda, core, parameters, args.preset, args.iterations, data_path);
|
|
else if (args.ngx_mode != "init") throw std::runtime_error("--ngx-mode must be init or evaluate");
|
|
check(destroy(parameters), "DestroyParameters(allocated)"); parameters = nullptr;
|
|
check(destroy(caps), "DestroyParameters(capabilities)"); caps = nullptr;
|
|
loaded_modules();
|
|
check(shutdown(), "NVSDK_NGX_CUDA_Shutdown"); initialized = false;
|
|
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=%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());
|
|
loaded_modules();
|
|
return 4;
|
|
}
|
|
}
|