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
@@ -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 |
|
| 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 |
|
| 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)
|
## Initial PSO and enhanced texture layouts (2026-10-01)
|
||||||
|
|
||||||
The backend now captures the initial PSO supplied to public CreateCommandList,
|
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
|
OptiScaler's default restore hotfixes are false; integration will keep
|
||||||
RestoreComputeSignature, RestoreGraphicSignature and ExtendedStateRestore
|
RestoreComputeSignature, RestoreGraphicSignature and ExtendedStateRestore
|
||||||
false because their original-method trampolines can bypass logical-list routing.
|
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)
|
## Native GPU resource-format conversion (2026-10-01)
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ param(
|
|||||||
[string]$NgxCore = $env:D4R_NGX_CORE,
|
[string]$NgxCore = $env:D4R_NGX_CORE,
|
||||||
[string]$DlssDll = $env:D4R_DLSS_DLL,
|
[string]$DlssDll = $env:D4R_DLSS_DLL,
|
||||||
[ValidateSet('init', 'evaluate', 'd3d12')][string]$NgxMode = 'init',
|
[ValidateSet('init', 'evaluate', 'd3d12')][string]$NgxMode = 'init',
|
||||||
|
[ValidateSet('driver','sdk','project')][string]$NgxAbi = 'driver',
|
||||||
|
[string]$OptiScalerDll,
|
||||||
[ValidateSet(5, 11, 13)][int]$Preset = 11,
|
[ValidateSet(5, 11, 13)][int]$Preset = 11,
|
||||||
[switch]$NgxOnly,
|
[switch]$NgxOnly,
|
||||||
[switch]$Trace,
|
[switch]$Trace,
|
||||||
@@ -141,6 +143,11 @@ try {
|
|||||||
(Join-Path $PackageRoot 'bin/wmma_gfx1201.hsaco'),
|
(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_enc1_layer_gfx1201.hsaco'),
|
||||||
(Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc2_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) {
|
||||||
if (!$NgxCore -or !$DlssDll) { throw 'Supply both -NgxCore and -DlssDll absolute paths.' }
|
if (!$NgxCore -or !$DlssDll) { throw 'Supply both -NgxCore and -DlssDll absolute paths.' }
|
||||||
if (![IO.Path]::IsPathRooted($NgxCore) -or ![IO.Path]::IsPathRooted($DlssDll)) {
|
if (![IO.Path]::IsPathRooted($NgxCore) -or ![IO.Path]::IsPathRooted($DlssDll)) {
|
||||||
@@ -251,7 +258,7 @@ try {
|
|||||||
$ngxArguments = @('--hip-root', $HipRoot, '--cuda-dll', $selectedCuda,
|
$ngxArguments = @('--hip-root', $HipRoot, '--cuda-dll', $selectedCuda,
|
||||||
'--ngx-core', $localCore, '--dlss-dll', $localDlss,
|
'--ngx-core', $localCore, '--dlss-dll', $localDlss,
|
||||||
'--nvapi-dll', (Join-Path $PackageRoot 'nvapi-compat/nvapi64.dll'),
|
'--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') {
|
if ($NgxMode -eq 'd3d12') {
|
||||||
# The driver NGX core resolves feature DLLs relative to its
|
# The driver NGX core resolves feature DLLs relative to its
|
||||||
# caller module as well as the executable. Keep the shim
|
# caller module as well as the executable. Keep the shim
|
||||||
@@ -259,11 +266,54 @@ try {
|
|||||||
$localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll'
|
$localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll'
|
||||||
Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim
|
Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim
|
||||||
Copy-Item -LiteralPath (Join-Path $bin 'pixel_convert_gfx1201.hsaco') -Destination $ngxRuntimeDirectory
|
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)
|
$ngxArguments += @('--module', $localShim, '--pixel-profile', $PixelProfile, '--barrier-mode', $BarrierMode)
|
||||||
if ($CommandListBackend) { $ngxArguments += @('--interop-mode', 'command-list') }
|
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' }
|
$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
|
$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) {
|
if ($ngxOk -and $RequireNativeNetwork) {
|
||||||
$hits = @()
|
$hits = @()
|
||||||
$nativeLayers = if ($Preset -eq 11) { @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0') }
|
$nativeLayers = if ($Preset -eq 11) { @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0') }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "d3d12_external.h"
|
#include "d3d12_external.h"
|
||||||
#include "ngx_parameters.h"
|
#include "ngx_parameters.h"
|
||||||
#include "ngx_cuda_evaluate.h"
|
#include "ngx_cuda_evaluate.h"
|
||||||
|
#include "ngx_public_abi.h"
|
||||||
#include <dxgi1_6.h>
|
#include <dxgi1_6.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -171,7 +172,15 @@ int main(int argc, char** argv) {
|
|||||||
using Evaluate = unsigned(*)(ID3D12CommandQueue*, void*, void*);
|
using Evaluate = unsigned(*)(ID3D12CommandQueue*, void*, void*);
|
||||||
using Release = unsigned(*)(void*); using Shutdown = unsigned(*)();
|
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)); };
|
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");
|
auto shutdown = shim.symbol<Shutdown>("NVSDK_NGX_D3D12_Shutdown");
|
||||||
struct ShutdownCleanup { Shutdown fn; ~ShutdownCleanup() { (void)fn(); } } shutdownCleanup{shutdown};
|
struct ShutdownCleanup { Shutdown fn; ~ShutdownCleanup() { (void)fn(); } } shutdownCleanup{shutdown};
|
||||||
void* parameters = nullptr; check(shim.symbol<Allocate>("NVSDK_NGX_D3D12_AllocateParameters")(¶meters), "AllocateParameters");
|
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.
|
// Native Windows backend. The Linux/Wine implementation remains separate.
|
||||||
#include "ngx_windows_runtime.h"
|
#include "ngx_windows_runtime.h"
|
||||||
|
#include <dxgi.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
@@ -21,7 +22,11 @@ unsigned allocate(void** out, bool caps) {
|
|||||||
if (!runtime || !out) return invalid;
|
if (!runtime || !out) return invalid;
|
||||||
void* value = d4r_ngx_parameters_create();
|
void* value = d4r_ngx_parameters_create();
|
||||||
if (!value) return failure;
|
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) {
|
if (caps) {
|
||||||
std::lock_guard<std::mutex> lock(runtime->mutex);
|
std::lock_guard<std::mutex> lock(runtime->mutex);
|
||||||
runtime->current(); void* official = nullptr;
|
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);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#define API extern "C" __declspec(dllexport)
|
#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);
|
std::lock_guard<std::mutex> lock(apiMutex);
|
||||||
return call([&] {
|
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")
|
if (const char* backend = std::getenv("D4R_D3D12_COMMAND_BACKEND"); backend && std::string(backend) == "1")
|
||||||
d4r::win::commands::install(device);
|
d4r::win::commands::install(device);
|
||||||
return 1u;
|
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) {
|
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);
|
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) {
|
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) {
|
||||||
// Driver core's CUDA ABI uses the numerical application identity.
|
std::lock_guard<std::mutex> lock(apiMutex);
|
||||||
return NVSDK_NGX_D3D12_Init_Ext(241534723ull, data, device, sdk, info);
|
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) {
|
API unsigned NVSDK_NGX_D3D12_AllocateParameters(void** p) {
|
||||||
std::lock_guard<std::mutex> lock(apiMutex); return call([&] { return allocate(p, false); });
|
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)
|
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",
|
std::fprintf(stderr, "EXCEPTION code=0x%08lx address=%p\n",
|
||||||
info->ExceptionRecord->ExceptionCode, info->ExceptionRecord->ExceptionAddress);
|
info->ExceptionRecord->ExceptionCode, info->ExceptionRecord->ExceptionAddress);
|
||||||
if (info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
|
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->Rdx),
|
||||||
static_cast<unsigned long long>(info->ContextRecord->R8),
|
static_cast<unsigned long long>(info->ContextRecord->R8),
|
||||||
static_cast<unsigned long long>(info->ContextRecord->R9));
|
static_cast<unsigned long long>(info->ContextRecord->R9));
|
||||||
loaded_modules();
|
|
||||||
wchar_t directory[32768]{};
|
wchar_t directory[32768]{};
|
||||||
const DWORD n = GetEnvironmentVariableW(L"D4R_DIAG_DIR", directory, 32768);
|
const DWORD n = GetEnvironmentVariableW(L"D4R_DIAG_DIR", directory, 32768);
|
||||||
if (n && n < 32768) {
|
if (n && n < 32768) {
|
||||||
@@ -115,6 +121,7 @@ struct Args {
|
|||||||
std::string ngx_core, dlss_dll;
|
std::string ngx_core, dlss_dll;
|
||||||
std::string nvapi_dll;
|
std::string nvapi_dll;
|
||||||
std::string ngx_abi = "driver";
|
std::string ngx_abi = "driver";
|
||||||
|
std::string ngx_frontend = "d4r";
|
||||||
std::string ngx_mode = "init";
|
std::string ngx_mode = "init";
|
||||||
unsigned preset = 11;
|
unsigned preset = 11;
|
||||||
std::string fixture_dir;
|
std::string fixture_dir;
|
||||||
@@ -145,6 +152,10 @@ struct Args {
|
|||||||
else if (key == "--dlss-dll") dlss_dll = value;
|
else if (key == "--dlss-dll") dlss_dll = value;
|
||||||
else if (key == "--nvapi-dll") nvapi_dll = value;
|
else if (key == "--nvapi-dll") nvapi_dll = value;
|
||||||
else if (key == "--ngx-abi") ngx_abi = 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 == "--ngx-mode") ngx_mode = value;
|
||||||
else if (key == "--preset") {
|
else if (key == "--preset") {
|
||||||
size_t end = 0;
|
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);
|
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()) +
|
if (!handle_) throw std::runtime_error("LoadLibrary " + utf8(path.c_str()) +
|
||||||
" Win32=" + std::to_string(GetLastError()));
|
" 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(const Library&) = delete;
|
||||||
Library& operator=(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);
|
Library dlss(dlss_path), core(core_path);
|
||||||
using Init = unsigned(*)(unsigned long long, const wchar_t*, const NgxFeatureCommonInfo*, unsigned);
|
using Init = unsigned(*)(unsigned long long, const wchar_t*, const NgxFeatureCommonInfo*, unsigned);
|
||||||
using DriverInit = unsigned(*)(unsigned long long, const wchar_t*, 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 Shutdown = unsigned(*)();
|
||||||
using Parameters = unsigned(*)(void**);
|
using Parameters = unsigned(*)(void**);
|
||||||
using Destroy = 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());
|
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)");
|
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 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;
|
bool initialized = true;
|
||||||
struct NgxCleanup { Shutdown shutdown; bool& active; ~NgxCleanup() { if (active) (void)shutdown(); } } nc{shutdown, initialized};
|
struct NgxCleanup { Shutdown shutdown; bool& active; ~NgxCleanup() { if (active) (void)shutdown(); } } nc{shutdown, initialized};
|
||||||
void* caps = nullptr;
|
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 "pixel_conversion.h"
|
||||||
#include "cuda_image_api.h"
|
#include "cuda_image_api.h"
|
||||||
#include "ngx_parameters.h"
|
#include "ngx_parameters.h"
|
||||||
|
#include "ngx_public_abi.h"
|
||||||
#include "d3d12_command_hooks.h"
|
#include "d3d12_command_hooks.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -54,6 +55,10 @@ struct Runtime {
|
|||||||
std::unique_ptr<SharedTimeline> timeline;
|
std::unique_ptr<SharedTimeline> timeline;
|
||||||
std::unique_ptr<PixelProgram> pixels;
|
std::unique_ptr<PixelProgram> pixels;
|
||||||
std::mutex mutex;
|
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 Init = unsigned(*)(unsigned long long, const wchar_t*, unsigned);
|
||||||
using Shutdown = unsigned(*)();
|
using Shutdown = unsigned(*)();
|
||||||
using Allocate = unsigned(*)(void**);
|
using Allocate = unsigned(*)(void**);
|
||||||
@@ -68,7 +73,8 @@ struct Runtime {
|
|||||||
Release release = nullptr;
|
Release release = nullptr;
|
||||||
Shutdown shutdown = 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")),
|
: 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()),
|
featureSearch(std::filesystem::path(diag::wide(env_path("D4R_DLSS_DLL"))).parent_path()),
|
||||||
external{hip}, images(cuda), device(d3d) {
|
external{hip}, images(cuda), device(d3d) {
|
||||||
@@ -104,7 +110,24 @@ struct Runtime {
|
|||||||
evaluate = core->symbol<Evaluate>("NVSDK_NGX_CUDA_EvaluateFeature");
|
evaluate = core->symbol<Evaluate>("NVSDK_NGX_CUDA_EvaluateFeature");
|
||||||
release = core->symbol<Release>("NVSDK_NGX_CUDA_ReleaseFeature");
|
release = core->symbol<Release>("NVSDK_NGX_CUDA_ReleaseFeature");
|
||||||
shutdown = core->symbol<Shutdown>("NVSDK_NGX_CUDA_Shutdown");
|
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;
|
initialized = true;
|
||||||
void* caps = nullptr;
|
void* caps = nullptr;
|
||||||
ngx_check(capabilities(&caps), "CUDA feature capabilities");
|
ngx_check(capabilities(&caps), "CUDA feature capabilities");
|
||||||
|
|||||||
Reference in new issue
Block a user