Forward Windows NGX project identity and validate frontend native network use

This commit is contained in:
Codex committed 2026-10-01 15:45:55 +03:00
1 parent 6ddf740877
commit 27d6a1230a
8 files changed
+207 -13

No files matched your search

+41 -1
View File
@@ -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 <absolute-path>`, 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)
+51 -1
View File
@@ -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') }
+10 -1
View File
@@ -1,6 +1,7 @@
#include "d3d12_external.h"
#include "ngx_parameters.h"
#include "ngx_cuda_evaluate.h"
#include "ngx_public_abi.h"
#include <dxgi1_6.h>
#include <memory>
#include <array>
@@ -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<Init>("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<Requirements>("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<ProjectInit>("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<Init>("NVSDK_NGX_D3D12_Init_Ext")(241534723ull, directory.c_str(), device.Get(), 0x15, nullptr), "D3D12 Init");
auto shutdown = shim.symbol<Shutdown>("NVSDK_NGX_D3D12_Shutdown");
struct ShutdownCleanup { Shutdown fn; ~ShutdownCleanup() { (void)fn(); } } shutdownCleanup{shutdown};
void* parameters = nullptr; check(shim.symbol<Allocate>("NVSDK_NGX_D3D12_AllocateParameters")(&parameters), "AllocateParameters");
+37 -6
View File
@@ -1,5 +1,6 @@
// Native Windows backend. The Linux/Wine implementation remains separate.
#include "ngx_windows_runtime.h"
#include <dxgi.h>
#include <unordered_map>
#include <functional>
@@ -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<std::mutex> 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<std::mutex> lock(apiMutex);
return call([&] {
if (!runtime) runtime = std::make_shared<d4r::win::Runtime>(device, app, data, sdk);
if (!runtime) runtime = std::make_shared<d4r::win::Runtime>(device, app, data, sdk, static_cast<const d4r::ngx::FeatureCommonInfo*>(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<std::mutex> lock(apiMutex);
return call([&] {
if (!project || !*project) return invalid;
d4r::ngx::ProjectIdentity identity{project, engine, version ? version : ""};
if (!runtime) runtime = std::make_shared<d4r::win::Runtime>(device, 0, data, sdk, static_cast<const d4r::ngx::FeatureCommonInfo*>(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<std::mutex> lock(apiMutex); return call([&] { return allocate(p, false); });
+15 -2
View File
@@ -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<unsigned long long>(info->ContextRecord->Rdx),
static_cast<unsigned long long>(info->ContextRecord->R8),
static_cast<unsigned long long>(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;
+4 -1
View File
@@ -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<ProjectInit>("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;
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <cstdint>
#include <string>
// 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);
}
+24 -1
View File
@@ -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 <chrono>
#include <memory>
@@ -54,6 +55,10 @@ struct Runtime {
std::unique_ptr<SharedTimeline> timeline;
std::unique_ptr<PixelProgram> pixels;
std::mutex mutex;
ngx::ProjectIdentity project;
ngx::FeatureCommonInfo common{};
std::vector<std::wstring> featurePaths;
std::vector<const wchar_t*> 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<Evaluate>("NVSDK_NGX_CUDA_EvaluateFeature");
release = core->symbol<Release>("NVSDK_NGX_CUDA_ReleaseFeature");
shutdown = core->symbol<Shutdown>("NVSDK_NGX_CUDA_Shutdown");
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<ProjectInit>("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<Init>("NVSDK_NGX_CUDA_Init")(app, data, sdk), "CUDA Init(driver ABI)");
}
initialized = true;
void* caps = nullptr;
ngx_check(capabilities(&caps), "CUDA feature capabilities");