diff --git a/docs/windows-rdna4-port.md b/docs/windows-rdna4-port.md index 12149af..f0b862c 100644 --- a/docs/windows-rdna4-port.md +++ b/docs/windows-rdna4-port.md @@ -38,6 +38,45 @@ Do not integrate NGX until the integer PTX workload is stable on the real GPU. | M8: standalone Windows D3D12 NGX harness | PASS for ordinary recorded EvaluateFeature and explicit boundaries: K/M, four frames each, no shim CPU image copies; both bit-exact against explicit boundary baselines | | M9: OptiScaler integration, profiling, installation | Pending | +## Public NGX identity and OptiScaler gate (2026-10-01) + +The Windows shim now implements D3D12 GetFeatureRequirements and forwards +Init_ProjectID to CUDA Init_ProjectID with the caller's project/engine/version. +The runtime owns the feature path strings and pointer list. The physical HIP +gfx1201 architecture and full DXGI adapter LUID determine SR support; other +features remain unsupported. Numeric driver initialization retains the tested +three-argument CUDA Init ABI. `-NgxAbi project` selects the public project path +in both CUDA and D3D12 probes. Capability parameter allocation is transactional. + +`ngx-project-api.zip` passes direct CUDA project initialization. +`d3d12-k-project-api.zip` and `d3d12-m-project-api.zip` pass four recorded +enhanced-barrier packed-format frames with 44 K / 40 M native launches. +All RGB values exactly match the independently quantised earlier baselines, +max absolute/relative error 0. Full rebuild and CTest pass 16/16 gates +(`project-api-ctest.log`). + +The runner now accepts `-OptiScalerDll `, creates a private +OptiScaler.ini and captures the frontend log. Native-network hit validation is +mandatory for the integration runs. The official 0.9.4 release silently chose +FSR despite DLSS=enabled on AMD: `optiscaler-m-first.zip` is correctly **FAIL** +with zero native launches. Current nightly 20261001 also gates DLSS on a +System32 NVIDIA driver; preloading our NVAPI triggered access violation +0xc0000005 in its loader hooks (`optiscaler-m-nightly-first.zip`). This is not +a DLSS success. The probe no longer preloads NVAPI before OptiScaler startup. +Crash capture avoids module resource enumeration in the exception filter, +guards reentrancy and records the minidump's module list instead. + +A local OptiScaler source fork starts from +`45a2001303ddff632e279f77aef85ceede5832cb`. Its explicit +`[DLSS] AllowExternalBackend=true` option requires an absolute NvngxPath with +the `d4r_WindowsBackendVersion` ABI-1 marker; it does not spoof HIP architecture. +The marker is GPU-free and safe during discovery. The pending patch also lets +the external backend load its own NVAPI provider through the original loader. +This source integration has not yet passed the frontend harness. +Microsoft Build Tools 17.14 / MSVC 14.44.35207 and SDK 10.0.26100 were installed +from the signature-verified official bootstrapper without restarting Windows. +No game files have been modified. + ## Initial PSO and enhanced texture layouts (2026-10-01) The backend now captures the initial PSO supplied to public CreateCommandList, @@ -74,7 +113,8 @@ gate. Unknown pre-initialization indirect signatures are still rejected. OptiScaler's default restore hotfixes are false; integration will keep RestoreComputeSignature, RestoreGraphicSignature and ExtendedStateRestore false because their original-method trampolines can bypass logical-list routing. -Actual OptiScaler execution remains untested; no game files have been changed. +Actual OptiScaler probes have exposed the frontend gate documented above; +no game files have been changed. ## Native GPU resource-format conversion (2026-10-01) diff --git a/scripts/windows/test-windows-rdna4.ps1 b/scripts/windows/test-windows-rdna4.ps1 index fdc0569..55d4873 100644 --- a/scripts/windows/test-windows-rdna4.ps1 +++ b/scripts/windows/test-windows-rdna4.ps1 @@ -8,6 +8,8 @@ param( [string]$NgxCore = $env:D4R_NGX_CORE, [string]$DlssDll = $env:D4R_DLSS_DLL, [ValidateSet('init', 'evaluate', 'd3d12')][string]$NgxMode = 'init', + [ValidateSet('driver','sdk','project')][string]$NgxAbi = 'driver', + [string]$OptiScalerDll, [ValidateSet(5, 11, 13)][int]$Preset = 11, [switch]$NgxOnly, [switch]$Trace, @@ -141,6 +143,11 @@ try { (Join-Path $PackageRoot 'bin/wmma_gfx1201.hsaco'), (Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc1_layer_gfx1201.hsaco'), (Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc2_layer_gfx1201.hsaco')) + if ($OptiScalerDll) { + if ($NgxMode -ne 'd3d12' -or !$CommandListBackend) { throw '-OptiScalerDll requires D3D12 and -CommandListBackend' } + if (![IO.Path]::IsPathRooted($OptiScalerDll)) { throw '-OptiScalerDll must be absolute' } + $files += $OptiScalerDll + } if ($NgxCore -or $DlssDll) { if (!$NgxCore -or !$DlssDll) { throw 'Supply both -NgxCore and -DlssDll absolute paths.' } if (![IO.Path]::IsPathRooted($NgxCore) -or ![IO.Path]::IsPathRooted($DlssDll)) { @@ -251,7 +258,7 @@ try { $ngxArguments = @('--hip-root', $HipRoot, '--cuda-dll', $selectedCuda, '--ngx-core', $localCore, '--dlss-dll', $localDlss, '--nvapi-dll', (Join-Path $PackageRoot 'nvapi-compat/nvapi64.dll'), - '--ngx-mode', $NgxMode, '--preset', "$Preset", '--iterations', "$Iterations") + '--ngx-mode', $NgxMode, '--ngx-abi', $NgxAbi, '--preset', "$Preset", '--iterations', "$Iterations") if ($NgxMode -eq 'd3d12') { # The driver NGX core resolves feature DLLs relative to its # caller module as well as the executable. Keep the shim @@ -259,11 +266,54 @@ try { $localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll' Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim Copy-Item -LiteralPath (Join-Path $bin 'pixel_convert_gfx1201.hsaco') -Destination $ngxRuntimeDirectory + if ($OptiScalerDll) { + $bridgeDirectory = Join-Path $ngxRuntimeDirectory 'd4r' + New-Item -ItemType Directory -Path $bridgeDirectory | Out-Null + Copy-Item -LiteralPath $localShim -Destination (Join-Path $bridgeDirectory '_nvngx.dll') + Copy-Item -LiteralPath (Join-Path $bin 'pixel_convert_gfx1201.hsaco') -Destination $bridgeDirectory + $localShim = Join-Path $ngxRuntimeDirectory 'OptiScaler.dll' + Copy-Item -LiteralPath $OptiScalerDll -Destination $localShim + $ini = @" +[Upscalers] +Dx12Upscaler=dlss +[FrameGen] +Enabled=false +FGInput=nofg +FGOutput=nofg +[DLSS] +Enabled=true +AllowExternalBackend=true +RenderPresetOverride=true +RenderPresetForAll=$Preset +UseGenericAppIdWithDlss=false +[Libraries] +NvngxPath=$bridgeDirectory +NvngxDlssPath=$localDlss +NvngxFeaturePath=$ngxRuntimeDirectory +[Hotfix] +RestoreComputeSignature=false +RestoreGraphicSignature=false +ExtendedStateRestore=false +[Log] +LogToFile=true +LogLevel=0 +[Menu] +DisableSplash=true +"@ + $ini | Set-Content -LiteralPath (Join-Path $ngxRuntimeDirectory 'OptiScaler.ini') -Encoding UTF8 + $summary.optiScaler = @{path=$OptiScalerDll; mode='standalone'; preset=$Preset} + $ngxArguments += @('--ngx-frontend', 'optiscaler') + } $ngxArguments += @('--module', $localShim, '--pixel-profile', $PixelProfile, '--barrier-mode', $BarrierMode) if ($CommandListBackend) { $ngxArguments += @('--interop-mode', 'command-list') } } $ngxName = if ($NgxMode -eq 'evaluate') { "ngx-evaluate-preset-$Preset" } elseif ($NgxMode -eq 'd3d12') { "d3d12-evaluate-preset-$Preset" } else { 'ngx-init' } $ngxOk = Invoke-Probe $ngxName $ngxExe $ngxArguments + if ($OptiScalerDll) { + Get-ChildItem -LiteralPath $ngxRuntimeDirectory -Filter '*.log' -File | + ForEach-Object { Copy-Item -LiteralPath $_.FullName -Destination (Join-Path $OutputDirectory ('optiscaler-' + $_.Name)) } + Copy-Item -LiteralPath (Join-Path $ngxRuntimeDirectory 'OptiScaler.ini') -Destination (Join-Path $OutputDirectory 'OptiScaler.ini') + } if ($ngxOk -and $RequireNativeNetwork) { $hits = @() $nativeLayers = if ($Preset -eq 11) { @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0') } diff --git a/tools/windows/d3d12_dlss_probe.cpp b/tools/windows/d3d12_dlss_probe.cpp index ef3bb9b..4aacd3b 100644 --- a/tools/windows/d3d12_dlss_probe.cpp +++ b/tools/windows/d3d12_dlss_probe.cpp @@ -1,6 +1,7 @@ #include "d3d12_external.h" #include "ngx_parameters.h" #include "ngx_cuda_evaluate.h" +#include "ngx_public_abi.h" #include #include #include @@ -171,7 +172,15 @@ int main(int argc, char** argv) { using Evaluate = unsigned(*)(ID3D12CommandQueue*, void*, void*); using Release = unsigned(*)(void*); using Shutdown = unsigned(*)(); auto check = [](unsigned result, const char* call) { if (result != 1) throw std::runtime_error(std::string(call) + " NGX=" + std::to_string(result)); }; - check(shim.symbol("NVSDK_NGX_D3D12_Init_Ext")(241534723ull, directory.c_str(), device.Get(), 0x15, nullptr), "D3D12 Init"); + d4r::ngx::FeatureDiscoveryInfo discovery{}; discovery.SDKVersion = 0x15; discovery.FeatureID = 1; + d4r::ngx::FeatureRequirement requirements{}; + using Requirements = unsigned(*)(IDXGIAdapter*,const d4r::ngx::FeatureDiscoveryInfo*,d4r::ngx::FeatureRequirement*); + check(shim.symbol("NVSDK_NGX_D3D12_GetFeatureRequirements")(adapter.Get(),&discovery,&requirements),"D3D12 feature requirements"); + if (requirements.FeatureSupported != 0) throw std::runtime_error("D3D12 DLSS requirements unsupported"); + if (args.ngx_abi == "project") { + using ProjectInit = unsigned(*)(const char*,int,const char*,const wchar_t*,ID3D12Device*,unsigned,const void*); + check(shim.symbol("NVSDK_NGX_D3D12_Init_ProjectID")("24480451-f00d-face-1304-0308dabad187",0,"1.0",directory.c_str(),device.Get(),0x15,nullptr),"D3D12 project Init"); + } else check(shim.symbol("NVSDK_NGX_D3D12_Init_Ext")(241534723ull, directory.c_str(), device.Get(), 0x15, nullptr), "D3D12 Init"); auto shutdown = shim.symbol("NVSDK_NGX_D3D12_Shutdown"); struct ShutdownCleanup { Shutdown fn; ~ShutdownCleanup() { (void)fn(); } } shutdownCleanup{shutdown}; void* parameters = nullptr; check(shim.symbol("NVSDK_NGX_D3D12_AllocateParameters")(¶meters), "AllocateParameters"); diff --git a/tools/windows/d4r_nvngx_windows.cpp b/tools/windows/d4r_nvngx_windows.cpp index bcd0dad..1746ee1 100644 --- a/tools/windows/d4r_nvngx_windows.cpp +++ b/tools/windows/d4r_nvngx_windows.cpp @@ -1,5 +1,6 @@ // Native Windows backend. The Linux/Wine implementation remains separate. #include "ngx_windows_runtime.h" +#include #include #include @@ -21,7 +22,11 @@ unsigned allocate(void** out, bool caps) { if (!runtime || !out) return invalid; void* value = d4r_ngx_parameters_create(); if (!value) return failure; - parameters.emplace(value, true); *out = value; + *out = nullptr; + struct LocalParameters { + void* p; + ~LocalParameters() { if (p) d4r_ngx_parameters_destroy(p); } + } owned{value}; if (caps) { std::lock_guard lock(runtime->mutex); runtime->current(); void* official = nullptr; @@ -36,14 +41,18 @@ unsigned allocate(void** out, bool caps) { if (d4r_ngx_get_void(official, name, &callback) == 1) d4r_ngx_set_void(value, name, callback); } } + parameters.emplace(value, true); *out = value; owned.p = nullptr; return 1; } } #define API extern "C" __declspec(dllexport) -API unsigned NVSDK_NGX_D3D12_Init_Ext(unsigned long long app, const wchar_t* data, ID3D12Device* device, unsigned sdk, const void*) { +// Capability marker for an explicit external backend selection. This function +// is safe to call during DLL discovery: no GPU/runtime initialization occurs. +API unsigned d4r_WindowsBackendVersion() { return 1; } +API unsigned NVSDK_NGX_D3D12_Init_Ext(unsigned long long app, const wchar_t* data, ID3D12Device* device, unsigned sdk, const void* info) { std::lock_guard lock(apiMutex); return call([&] { - if (!runtime) runtime = std::make_shared(device, app, data, sdk); + if (!runtime) runtime = std::make_shared(device, app, data, sdk, static_cast(info)); if (const char* backend = std::getenv("D4R_D3D12_COMMAND_BACKEND"); backend && std::string(backend) == "1") d4r::win::commands::install(device); return 1u; @@ -52,9 +61,31 @@ API unsigned NVSDK_NGX_D3D12_Init_Ext(unsigned long long app, const wchar_t* dat API unsigned NVSDK_NGX_D3D12_Init(unsigned long long app, const wchar_t* data, ID3D12Device* device, const void* info, unsigned sdk) { return NVSDK_NGX_D3D12_Init_Ext(app, data, device, sdk, info); } -API unsigned NVSDK_NGX_D3D12_Init_ProjectID(const char*, int, const char*, const wchar_t* data, ID3D12Device* device, unsigned sdk, const void* info) { - // Driver core's CUDA ABI uses the numerical application identity. - return NVSDK_NGX_D3D12_Init_Ext(241534723ull, data, device, sdk, info); +API unsigned NVSDK_NGX_D3D12_Init_ProjectID(const char* project, int engine, const char* version, const wchar_t* data, ID3D12Device* device, unsigned sdk, const void* info) { + std::lock_guard lock(apiMutex); + return call([&] { + if (!project || !*project) return invalid; + d4r::ngx::ProjectIdentity identity{project, engine, version ? version : ""}; + if (!runtime) runtime = std::make_shared(device, 0, data, sdk, static_cast(info), &identity); + if (const char* backend = std::getenv("D4R_D3D12_COMMAND_BACKEND"); backend && std::string(backend) == "1") d4r::win::commands::install(device); + return 1u; + }); +} +API unsigned NVSDK_NGX_D3D12_GetFeatureRequirements(IDXGIAdapter* adapter, const d4r::ngx::FeatureDiscoveryInfo* info, + d4r::ngx::FeatureRequirement* requirements) { + if (!adapter || !info || !requirements) return invalid; + return call([&] { + *requirements = {}; requirements->FeatureSupported = 16; // Unsupported feature. + if (info->FeatureID != 1) return 1u; + 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); + 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); + return 1u; + }); } API unsigned NVSDK_NGX_D3D12_AllocateParameters(void** p) { std::lock_guard lock(apiMutex); return call([&] { return allocate(p, false); }); diff --git a/tools/windows/diagnostic.h b/tools/windows/diagnostic.h index 1c7bbe5..9ab41da 100644 --- a/tools/windows/diagnostic.h +++ b/tools/windows/diagnostic.h @@ -55,6 +55,13 @@ inline void loaded_modules() } inline LONG WINAPI unhandled(EXCEPTION_POINTERS* info) { + // Loader hooks can fault while holding the loader lock. Do not enumerate + // modules or read their resources here; the dump contains the module list. + // Guard the final filter as well as the first-chance handler against a + // second exception inside DbgHelp. + static LONG dumping = 0; + if (InterlockedCompareExchange(&dumping, 1, 0) != 0) + return EXCEPTION_EXECUTE_HANDLER; std::fprintf(stderr, "EXCEPTION code=0x%08lx address=%p\n", info->ExceptionRecord->ExceptionCode, info->ExceptionRecord->ExceptionAddress); if (info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && @@ -69,7 +76,6 @@ inline LONG WINAPI unhandled(EXCEPTION_POINTERS* info) static_cast(info->ContextRecord->Rdx), static_cast(info->ContextRecord->R8), static_cast(info->ContextRecord->R9)); - loaded_modules(); wchar_t directory[32768]{}; const DWORD n = GetEnvironmentVariableW(L"D4R_DIAG_DIR", directory, 32768); if (n && n < 32768) { @@ -115,6 +121,7 @@ struct Args { std::string ngx_core, dlss_dll; std::string nvapi_dll; std::string ngx_abi = "driver"; + std::string ngx_frontend = "d4r"; std::string ngx_mode = "init"; unsigned preset = 11; std::string fixture_dir; @@ -145,6 +152,10 @@ struct Args { else if (key == "--dlss-dll") dlss_dll = value; else if (key == "--nvapi-dll") nvapi_dll = value; else if (key == "--ngx-abi") ngx_abi = value; + else if (key == "--ngx-frontend") { + if (value != "d4r" && value != "optiscaler") throw std::runtime_error("ngx-frontend must be d4r or optiscaler"); + ngx_frontend = value; + } else if (key == "--ngx-mode") ngx_mode = value; else if (key == "--preset") { size_t end = 0; @@ -178,7 +189,9 @@ public: LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS); if (!handle_) throw std::runtime_error("LoadLibrary " + utf8(path.c_str()) + " Win32=" + std::to_string(GetLastError())); - std::printf("LOAD requested=%s\n", utf8(path.c_str()).c_str()); + wchar_t actual[32768]{}; + GetModuleFileNameW(handle_, actual, 32768); + std::printf("LOAD requested=%s actual=%s\n", utf8(path.c_str()).c_str(), utf8(actual).c_str()); } Library(const Library&) = delete; Library& operator=(const Library&) = delete; diff --git a/tools/windows/ngx_cuda_init_probe.cpp b/tools/windows/ngx_cuda_init_probe.cpp index 22628a5..a5fffe5 100644 --- a/tools/windows/ngx_cuda_init_probe.cpp +++ b/tools/windows/ngx_cuda_init_probe.cpp @@ -67,6 +67,7 @@ int main(int argc, char** argv) Library dlss(dlss_path), core(core_path); using Init = unsigned(*)(unsigned long long, const wchar_t*, const NgxFeatureCommonInfo*, unsigned); using DriverInit = unsigned(*)(unsigned long long, const wchar_t*, 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*); @@ -89,7 +90,9 @@ int main(int argc, char** argv) std::printf("STAGE NVSDK_NGX_CUDA_Init sdk=0x15 core=%s dlss=%s\n", args.ngx_core.c_str(), args.dlss_dll.c_str()); if (args.ngx_abi == "driver") check(driver_init(241534723ull, data_path.c_str(), 0x15), "NVSDK_NGX_CUDA_Init(driver ABI)"); else if (args.ngx_abi == "sdk") check(init(241534723ull, data_path.c_str(), &common, 0x15), "NVSDK_NGX_CUDA_Init(SDK ABI)"); - else throw std::runtime_error("--ngx-abi must be driver or sdk"); + else if (args.ngx_abi == "project") check(core.symbol("NVSDK_NGX_CUDA_Init_ProjectID")( + "24480451-f00d-face-1304-0308dabad187", 0, "1.0", 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; diff --git a/tools/windows/ngx_public_abi.h b/tools/windows/ngx_public_abi.h new file mode 100644 index 0000000..126c864 --- /dev/null +++ b/tools/windows/ngx_public_abi.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include + +// Public NGX driver export ABI, also used by the upstream shim and OptiScaler. +// NVIDIA SDK headers or binaries are not build dependencies. +namespace d4r::ngx { +struct PathListInfo { const wchar_t* const* Path; unsigned Length; }; +struct LoggingInfo { void* LoggingCallback; int MinimumLoggingLevel; bool DisableOtherLoggingSinks; }; +struct FeatureCommonInfo { PathListInfo PathListInfo; void* InternalData; LoggingInfo LoggingInfo; }; +struct ProjectDescription { const char* ProjectId; int EngineType; const char* EngineVersion; }; +struct ApplicationIdentifier { + unsigned IdentifierType; + union Value { ProjectDescription ProjectDesc; unsigned long long ApplicationId; } v; +}; +struct FeatureDiscoveryInfo { + unsigned SDKVersion, FeatureID; + ApplicationIdentifier Identifier; + const wchar_t* ApplicationDataPath; + const FeatureCommonInfo* FeatureInfo; +}; +struct FeatureRequirement { unsigned FeatureSupported, MinHWArchitecture; char MinOSVersion[255]; }; +struct ProjectIdentity { std::string id; int engine; std::string version; }; +static_assert(sizeof(FeatureCommonInfo) == 40 && sizeof(FeatureDiscoveryInfo) == 56 && sizeof(FeatureRequirement) == 264); +} diff --git a/tools/windows/ngx_windows_runtime.h b/tools/windows/ngx_windows_runtime.h index 392299b..169d926 100644 --- a/tools/windows/ngx_windows_runtime.h +++ b/tools/windows/ngx_windows_runtime.h @@ -3,6 +3,7 @@ #include "pixel_conversion.h" #include "cuda_image_api.h" #include "ngx_parameters.h" +#include "ngx_public_abi.h" #include "d3d12_command_hooks.h" #include #include @@ -54,6 +55,10 @@ struct Runtime { std::unique_ptr timeline; std::unique_ptr pixels; std::mutex mutex; + ngx::ProjectIdentity project; + ngx::FeatureCommonInfo common{}; + std::vector featurePaths; + std::vector featurePathPointers; using Init = unsigned(*)(unsigned long long, const wchar_t*, unsigned); using Shutdown = unsigned(*)(); using Allocate = unsigned(*)(void**); @@ -68,7 +73,8 @@ struct Runtime { Release release = nullptr; Shutdown shutdown = nullptr; - Runtime(ID3D12Device* d3d, unsigned long long app, const wchar_t* data, unsigned sdk) + Runtime(ID3D12Device* d3d, unsigned long long app, const wchar_t* data, unsigned sdk, + const ngx::FeatureCommonInfo* info = nullptr, const ngx::ProjectIdentity* identity = nullptr) : hip(env_path("D4R_HIP_ROOT")), cuda(env_path("D4R_NVCUDA_DLL")), featureSearch(std::filesystem::path(diag::wide(env_path("D4R_DLSS_DLL"))).parent_path()), external{hip}, images(cuda), device(d3d) { @@ -104,7 +110,24 @@ struct Runtime { evaluate = core->symbol("NVSDK_NGX_CUDA_EvaluateFeature"); release = core->symbol("NVSDK_NGX_CUDA_ReleaseFeature"); shutdown = core->symbol("NVSDK_NGX_CUDA_Shutdown"); - ngx_check(core->symbol("NVSDK_NGX_CUDA_Init")(app, data, sdk), "CUDA Init(driver ABI)"); + if (identity) { + if (identity->id.empty()) throw std::runtime_error("Empty NGX project identity"); + project = *identity; + featurePaths.push_back(std::filesystem::path(diag::wide(env_path("D4R_DLSS_DLL"))).parent_path().wstring()); + if (info) { + if (info->PathListInfo.Length > 1024 || (info->PathListInfo.Length && !info->PathListInfo.Path)) throw std::runtime_error("Invalid NGX feature path list"); + for (unsigned i = 0; i < info->PathListInfo.Length; ++i) if (info->PathListInfo.Path[i]) featurePaths.emplace_back(info->PathListInfo.Path[i]); + if (sdk >= 0x14) common.LoggingInfo = info->LoggingInfo; + } + for (const auto& path : featurePaths) featurePathPointers.push_back(path.c_str()); + common.PathListInfo = {featurePathPointers.data(), unsigned(featurePathPointers.size())}; + using ProjectInit = unsigned(*)(const char*, int, const char*, const wchar_t*, unsigned, const ngx::FeatureCommonInfo*); + std::printf("D4R_IDENTITY project=%s engine=%d version=%s sdk=0x%x\n", project.id.c_str(),project.engine,project.version.c_str(),sdk); + ngx_check(core->symbol("NVSDK_NGX_CUDA_Init_ProjectID")(project.id.c_str(),project.engine,project.version.c_str(),data,sdk,&common), "CUDA Init_ProjectID"); + } else { + std::printf("D4R_IDENTITY application=%llu sdk=0x%x\n", app,sdk); + ngx_check(core->symbol("NVSDK_NGX_CUDA_Init")(app, data, sdk), "CUDA Init(driver ABI)"); + } initialized = true; void* caps = nullptr; ngx_check(capabilities(&caps), "CUDA feature capabilities");