Forward Windows NGX project identity and validate frontend native network use
This commit is contained in:
1 parent
6ddf740877
commit
27d6a1230a
8 files changed
+208
-14
No files matched your search
@@ -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")(¶meters), "AllocateParameters");
|
||||
|
||||
@@ -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); });
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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");
|
||||
ngx_check(core->symbol<Init>("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<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");
|
||||
|
||||
Reference in new issue
Block a user