Skip to content

Commit 3df8499

Browse files
committed
fix(ngx): track native initialization and shutdown per device
1 parent 1a26bda commit 3df8499

15 files changed

Lines changed: 662 additions & 332 deletions

‎.github/workflows/just_build_no_signature.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ jobs:
128128
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
129129
$vs = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
130130
$vcvars = Join-Path $vs 'VC\Auxiliary\Build\vcvars64.bat'
131-
foreach ($name in @('Aurora_DLSSG_Frame_Guard_Tests','Aurora_Provider_Handle_Tests','Aurora_Input_Lock_Tests','Aurora_Streamline_Binding_Tests','Aurora_Provider_Create_Tests','Aurora_Provider_Publication_Tests')) {
131+
foreach ($name in @('Aurora_DLSSG_Frame_Guard_Tests','Aurora_Provider_Handle_Tests','Aurora_Input_Lock_Tests','Aurora_Streamline_Binding_Tests','Aurora_Provider_Create_Tests','Aurora_Provider_Publication_Tests','Aurora_Native_Device_Tests')) {
132132
$command = 'call "' + $vcvars + '" && cl /nologo /EHsc /std:c++20 /I OptiScaler tests\' + $name + '.cpp /Fe:x64\' + $name + '.exe && x64\' + $name + '.exe'
133133
& $env:ComSpec /d /c $command
134134
if ($LASTEXITCODE) { throw "Compatibility guard test failed: $name" }

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ Read `docs/CODEX_HANDOFF.md` before continuing. Source repository is this direct
55
- Active branch: `Compatibility-fixes`, based on `aurora` at `e1673a16`.
66
- The user discontinued RC3 installer development. Preserve its historical branches; do not bring installer changes into this branch.
77
- Focus on evidenced game compatibility and performance defects. Review upstream/fork patches before adopting them; record provenance and deferred risks.
8-
- Ordinary commits and pushes to `Compatibility-fixes` are authorized. Do not merge into `aurora`, force-push, or publish Releases.
8+
- Ordinary commits and pushes to `Compatibility-fixes` are authorized. The user's latest 2026-09-17 instruction also authorizes synchronizing to `aurora` after the ongoing lifecycle fixes, review, focused checks and full DLL build are complete; real-game testing is deferred and is not a merge prerequisite. Do not merge unfinished lifecycle work, force-push, or publish Releases. Record unverified game behavior accurately.
99
- Do not modify installed games or claim CPU tests/builds establish GPU compatibility. Preserve native Streamline 1.x, Aurora's verified 6X path, and `DualFeature=false` behavior.
1010
- Run focused checks and the full DLL build for affected C++ changes. Do not rerun unrelated legacy installer suites or produce replacement archives.

‎OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp‎

Lines changed: 52 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,17 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext(unsigned long long InApp
182182
{
183183
LOG_INFO("calling NVNGXProxy::D3D12_Init_Ext");
184184

185-
auto result = NVNGXProxy::D3D12_Init_Ext()(InApplicationId, InApplicationDataPath, InDevice, InSDKVersion,
186-
&localFeatureInfo);
185+
auto result = NVNGXProxy::RunDx12Init(InDevice,
186+
[&]
187+
{
188+
return NVNGXProxy::D3D12_Init_Ext()(
189+
InApplicationId, InApplicationDataPath, InDevice,
190+
InSDKVersion, &localFeatureInfo);
191+
});
187192
LOG_INFO("calling NVNGXProxy::D3D12_Init_Ext result: {0:X}", (UINT) result);
188193

189-
if (result == NVSDK_NGX_Result_Success)
190-
NVNGXProxy::SetDx12Inited(true);
194+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
195+
return result;
191196
}
192197
else
193198
{
@@ -254,13 +259,18 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init(unsigned long long InApplica
254259
{
255260
LOG_INFO("calling NVNGXProxy::D3D12_Init");
256261

257-
auto result = NVNGXProxy::D3D12_Init()(InApplicationId, InApplicationDataPath, InDevice, &localFeatureInfo,
258-
InSDKVersion);
262+
auto result =
263+
NVNGXProxy::RunDx12Init(InDevice,
264+
[&]
265+
{
266+
return NVNGXProxy::D3D12_Init()(InApplicationId, InApplicationDataPath,
267+
InDevice, &localFeatureInfo, InSDKVersion);
268+
});
259269

260270
LOG_INFO("calling NVNGXProxy::D3D12_Init result: {0:X}", (UINT) result);
261271

262-
if (result == NVSDK_NGX_Result_Success)
263-
NVNGXProxy::SetDx12Inited(true);
272+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
273+
return result;
264274
}
265275
}
266276

@@ -313,13 +323,18 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_ProjectID(const char* InProj
313323
LOG_INFO("calling NVNGXProxy::D3D12_Init_ProjectID");
314324

315325
auto result =
316-
NVNGXProxy::D3D12_Init_ProjectID()(InProjectId, InEngineType, InEngineVersion, InApplicationDataPath,
317-
InDevice, InSDKVersion, &localFeatureInfo);
326+
NVNGXProxy::RunDx12Init(InDevice,
327+
[&]
328+
{
329+
return NVNGXProxy::D3D12_Init_ProjectID()(
330+
InProjectId, InEngineType, InEngineVersion, InApplicationDataPath,
331+
InDevice, InSDKVersion, &localFeatureInfo);
332+
});
318333

319334
LOG_INFO("calling NVNGXProxy::D3D12_Init_ProjectID result: {0:X}", (UINT) result);
320335

321-
if (result == NVSDK_NGX_Result_Success)
322-
NVNGXProxy::SetDx12Inited(true);
336+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
337+
return result;
323338
}
324339
}
325340

@@ -373,79 +388,51 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_with_ProjectID(
373388

374389
#pragma region DLSS Shutdown Calls
375390

376-
static NVSDK_NGX_Result ShutdownD3D12(bool shutdownProvider)
391+
static NVSDK_NGX_Result ShutdownD3D12(ID3D12Device* device)
377392
{
378-
shutdown = true;
379-
State::Instance().nvngxDx12Inited = false;
380-
381-
D3D12Device = nullptr;
382-
383-
State::Instance().currentFeature = nullptr;
384-
385-
// Unhooking and cleaning stuff causing issues during shutdown.
386-
// Disabled for now to check if it cause any issues
387-
// UnhookAll();
388-
DLSSFeatureDx12::Shutdown(D3D12Device);
393+
// Retain the existing process-exit workaround. During normal shutdown,
394+
// failure must preserve native ownership and local state for a retry.
395+
if (!State::Instance().isShuttingDown)
396+
{
397+
const auto result = NVNGXProxy::ShutdownDx12(device);
398+
if (result != NVSDK_NGX_Result_Success)
399+
return result;
400+
}
389401

390-
// Added `&& !State::Instance().isShuttingDown` hack for crash on exit
391-
if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited() &&
392-
NVNGXProxy::D3D12_Shutdown() != nullptr && !State::Instance().isShuttingDown)
402+
if (State::Instance().activeFgNvngx != FGNvngxReplacement::None)
393403
{
394-
auto result = NVNGXProxy::D3D12_Shutdown()();
395-
NVNGXProxy::SetDx12Inited(false);
404+
if (device)
405+
Nvngx_FG::D3D12_Shutdown1(device);
406+
else
407+
Nvngx_FG::D3D12_Shutdown();
396408
}
397409

398-
// Unhooking and cleaning stuff causing issues during shutdown.
399-
// Disabled for now to check if it cause any issues
400-
// HooksDx::UnHook();
410+
if (device && device != D3D12Device)
411+
return NVSDK_NGX_Result_Success;
412+
413+
shutdown = true;
414+
DLSSFeatureDx12::ResetAfterNativeShutdown();
415+
if (State::Instance().api == API::DX12)
416+
State::Instance().currentFeature = nullptr;
401417

402-
// Disabled to prevent crash
403418
if (State::Instance().currentFG != nullptr && State::Instance().activeFgInput == FGInput::Upscaler)
404419
{
405420
if (State::Instance().isShuttingDown)
406421
State::Instance().currentFG->Shutdown();
407422
else
408423
State::Instance().currentFG->DestroyFGContext();
409-
410424
State::Instance().clearCapturedHudlesses = true;
411425
}
412426

413-
shutdown = false;
414-
415-
if (shutdownProvider && State::Instance().activeFgNvngx != FGNvngxReplacement::None)
416-
{
417-
Nvngx_FG::D3D12_Shutdown();
418-
}
419-
427+
D3D12Device = nullptr;
420428
State::Instance().nvngxDx12Inited = false;
421-
429+
shutdown = false;
422430
return NVSDK_NGX_Result_Success;
423431
}
424432

425-
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Shutdown(void) { return ShutdownD3D12(true); }
426-
427-
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Shutdown1(ID3D12Device* InDevice)
428-
{
429-
shutdown = true;
430-
State::Instance().nvngxDx12Inited = false;
431-
432-
if (State::Instance().activeFgNvngx != FGNvngxReplacement::None)
433-
{
434-
Nvngx_FG::D3D12_Shutdown1(InDevice);
435-
}
433+
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Shutdown(void) { return ShutdownD3D12(nullptr); }
436434

437-
// Added `&& !State::Instance().isShuttingDown` hack for crash on exit
438-
if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited() &&
439-
NVNGXProxy::D3D12_Shutdown1() != nullptr && !State::Instance().isShuttingDown)
440-
{
441-
auto result = NVNGXProxy::D3D12_Shutdown1()(InDevice);
442-
NVNGXProxy::SetDx12Inited(false);
443-
}
444-
445-
// The provider already received Shutdown1. Run local cleanup without a second,
446-
// global provider shutdown which can invalidate other native device state.
447-
return ShutdownD3D12(false);
448-
}
435+
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Shutdown1(ID3D12Device* InDevice) { return ShutdownD3D12(InDevice); }
449436

450437
#pragma endregion
451438

‎OptiScaler/inputs/NVNGX_DLSS_Vk.cpp‎

Lines changed: 63 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,17 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Init_Ext2(
177177
if (NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::VULKAN_Init_Ext2() != nullptr)
178178
{
179179
LOG_INFO("calling NVNGXProxy::VULKAN_Init_Ext2");
180-
auto result = NVNGXProxy::VULKAN_Init_Ext2()(InApplicationId, InApplicationDataPath, InInstance, InPD,
181-
InDevice, InGIPA, InGDPA, InSDKVersion, &localFeatureInfo);
180+
auto result = NVNGXProxy::RunVulkanInit(InDevice,
181+
[&]
182+
{
183+
return NVNGXProxy::VULKAN_Init_Ext2()(
184+
InApplicationId, InApplicationDataPath, InInstance, InPD,
185+
InDevice, InGIPA, InGDPA, InSDKVersion, &localFeatureInfo);
186+
});
182187
LOG_INFO("NVNGXProxy::VULKAN_Init_Ext2 result: {0:X}", (UINT) result);
183188

184-
if (result == NVSDK_NGX_Result_Success)
185-
NVNGXProxy::SetVulkanInited(true);
189+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
190+
return result;
186191
}
187192
}
188193

@@ -283,12 +288,17 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Init_Ext(unsigned long long InAp
283288
if (NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::VULKAN_Init_Ext() != nullptr)
284289
{
285290
LOG_INFO("calling NVNGXProxy::VULKAN_Init_Ext");
286-
auto result = NVNGXProxy::VULKAN_Init_Ext()(InApplicationId, InApplicationDataPath, InInstance, InPD,
287-
InDevice, InSDKVersion, &localFeatureInfo);
291+
auto result = NVNGXProxy::RunVulkanInit(InDevice,
292+
[&]
293+
{
294+
return NVNGXProxy::VULKAN_Init_Ext()(
295+
InApplicationId, InApplicationDataPath, InInstance, InPD,
296+
InDevice, InSDKVersion, &localFeatureInfo);
297+
});
288298
LOG_INFO("NVNGXProxy::VULKAN_Init_Ext result: {0:X}", (UINT) result);
289299

290-
if (result == NVSDK_NGX_Result_Success)
291-
NVNGXProxy::SetVulkanInited(true);
300+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
301+
return result;
292302
}
293303
}
294304

@@ -326,13 +336,18 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Init_ProjectID_Ext(
326336
if (NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::VULKAN_Init_ProjectID_Ext() != nullptr)
327337
{
328338
LOG_INFO("calling NVNGXProxy::VULKAN_Init_ProjectID_Ext");
329-
auto result = NVNGXProxy::VULKAN_Init_ProjectID_Ext()(InProjectId, InEngineType, InEngineVersion,
330-
InApplicationDataPath, InInstance, InPD, InDevice,
331-
InGIPA, InGDPA, InSDKVersion, &localFeatureInfo);
339+
auto result = NVNGXProxy::RunVulkanInit(InDevice,
340+
[&]
341+
{
342+
return NVNGXProxy::VULKAN_Init_ProjectID_Ext()(
343+
InProjectId, InEngineType, InEngineVersion,
344+
InApplicationDataPath, InInstance, InPD, InDevice, InGIPA,
345+
InGDPA, InSDKVersion, &localFeatureInfo);
346+
});
332347
LOG_INFO("NVNGXProxy::VULKAN_Init_ProjectID_Ext result: {0:X}", (UINT) result);
333348

334-
if (result == NVSDK_NGX_Result_Success)
335-
NVNGXProxy::SetVulkanInited(true);
349+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
350+
return result;
336351
}
337352
}
338353

@@ -379,12 +394,17 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Init(unsigned long long InApplic
379394
if (NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::VULKAN_Init() != nullptr)
380395
{
381396
LOG_INFO("calling NVNGXProxy::VULKAN_Init");
382-
auto result = NVNGXProxy::VULKAN_Init()(InApplicationId, InApplicationDataPath, InInstance, InPD, InDevice,
383-
InGIPA, InGDPA, &localFeatureInfo, InSDKVersion);
397+
auto result = NVNGXProxy::RunVulkanInit(InDevice,
398+
[&]
399+
{
400+
return NVNGXProxy::VULKAN_Init()(
401+
InApplicationId, InApplicationDataPath, InInstance, InPD,
402+
InDevice, InGIPA, InGDPA, &localFeatureInfo, InSDKVersion);
403+
});
384404
LOG_INFO("NVNGXProxy::VULKAN_Init result: {0:X}", (UINT) result);
385405

386-
if (result == NVSDK_NGX_Result_Success)
387-
NVNGXProxy::SetVulkanInited(true);
406+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
407+
return result;
388408
}
389409
}
390410

@@ -425,13 +445,18 @@ NVSDK_NGX_VULKAN_Init_ProjectID(const char* InProjectId, NVSDK_NGX_EngineType In
425445
if (NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::VULKAN_Init_ProjectID() != nullptr)
426446
{
427447
LOG_INFO("calling NVNGXProxy::VULKAN_Init_ProjectID");
428-
auto result = NVNGXProxy::VULKAN_Init_ProjectID()(InProjectId, InEngineType, InEngineVersion,
429-
InApplicationDataPath, InInstance, InPD, InDevice, InGIPA,
430-
InGDPA, InSDKVersion, &localFeatureInfo);
448+
auto result = NVNGXProxy::RunVulkanInit(InDevice,
449+
[&]
450+
{
451+
return NVNGXProxy::VULKAN_Init_ProjectID()(
452+
InProjectId, InEngineType, InEngineVersion,
453+
InApplicationDataPath, InInstance, InPD, InDevice, InGIPA,
454+
InGDPA, InSDKVersion, &localFeatureInfo);
455+
});
431456
LOG_INFO("NVNGXProxy::VULKAN_Init_ProjectID result: {0:X}", (UINT) result);
432457

433-
if (result == NVSDK_NGX_Result_Success)
434-
NVNGXProxy::SetVulkanInited(true);
458+
if (result == NVSDK_NGX_Result_FAIL_NotInitialized)
459+
return result;
435460
}
436461
}
437462

@@ -1165,60 +1190,31 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_EvaluateFeature(VkCommandBuffer
11651190
return upscaleResult ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail;
11661191
}
11671192

1168-
static NVSDK_NGX_Result ShutdownVulkan(bool shutdownProvider)
1193+
static NVSDK_NGX_Result ShutdownVulkan(VkDevice device)
11691194
{
1170-
shutdown = true;
1195+
const auto result = NVNGXProxy::ShutdownVulkan(device);
1196+
if (result != NVSDK_NGX_Result_Success)
1197+
return result;
11711198

1172-
// for (auto const& [key, val] : VkContexts) {
1173-
// if (val.feature)
1174-
// NVSDK_NGX_VULKAN_ReleaseFeature(val.feature->Handle());
1175-
// }
1199+
if (device)
1200+
Nvngx_FG::VULKAN_Shutdown1(device);
1201+
else
1202+
Nvngx_FG::VULKAN_Shutdown();
11761203

1177-
// VkContexts.clear();
1204+
if (device && device != vkDevice)
1205+
return NVSDK_NGX_Result_Success;
11781206

1207+
shutdown = true;
11791208
vkInstance = nullptr;
11801209
vkPD = nullptr;
11811210
vkDevice = nullptr;
1182-
1183-
State::Instance().currentFeature = nullptr;
1184-
1185-
if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsVulkanInited() &&
1186-
NVNGXProxy::VULKAN_Shutdown() != nullptr)
1187-
{
1188-
auto result = NVNGXProxy::VULKAN_Shutdown()();
1189-
NVNGXProxy::SetVulkanInited(false);
1190-
}
1191-
1192-
// Unhooking and cleaning stuff causing issues during shutdown.
1193-
// Disabled for now to check if it cause any issues
1194-
// MenuOverlayVk::UnHookVk();
1195-
1196-
if (shutdownProvider)
1197-
Nvngx_FG::VULKAN_Shutdown();
1198-
1199-
shutdown = false;
1211+
if (State::Instance().api == API::Vulkan)
1212+
State::Instance().currentFeature = nullptr;
12001213
State::Instance().nvngxVkInited = false;
1201-
1214+
shutdown = false;
12021215
return NVSDK_NGX_Result_Success;
12031216
}
12041217

1205-
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Shutdown(void) { return ShutdownVulkan(true); }
1218+
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Shutdown(void) { return ShutdownVulkan(nullptr); }
12061219

1207-
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Shutdown1(VkDevice InDevice)
1208-
{
1209-
shutdown = true;
1210-
1211-
if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsVulkanInited() &&
1212-
NVNGXProxy::VULKAN_Shutdown1() != nullptr)
1213-
{
1214-
auto result = NVNGXProxy::VULKAN_Shutdown1()(InDevice);
1215-
NVNGXProxy::SetVulkanInited(false);
1216-
}
1217-
1218-
Nvngx_FG::VULKAN_Shutdown1(InDevice);
1219-
1220-
shutdown = false;
1221-
1222-
// Do not follow the provider's device shutdown with a second global shutdown.
1223-
return ShutdownVulkan(false);
1224-
}
1220+
NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_Shutdown1(VkDevice InDevice) { return ShutdownVulkan(InDevice); }

0 commit comments

Comments
 (0)