Skip to content

Commit 6f5597a

Browse files
committed
fix(framegen): exclude provider teardown from active calls
1 parent 3685ab3 commit 6f5597a

11 files changed

Lines changed: 443 additions & 88 deletions

‎.github/workflows/just_build_no_signature.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ jobs:
133133
& $env:ComSpec /d /c $command
134134
if ($LASTEXITCODE) { throw "Compatibility guard test failed: $name" }
135135
}
136-
foreach ($script in @('test_shutdown_routing.py','test_provider_publication_routes.py','test_provider_dll_boundary.py','test_combo_release.py','test_native_operation_routes.py','test_native_module_publication.py','test_native_init_scopes.py','test_ngx_init_paths.py','test_ngx_init_metadata.py','test_provider_release_admission.py')) {
136+
foreach ($script in @('test_shutdown_routing.py','test_provider_publication_routes.py','test_provider_dll_boundary.py','test_combo_release.py','test_native_operation_routes.py','test_native_module_publication.py','test_native_init_scopes.py','test_ngx_init_paths.py','test_ngx_init_metadata.py','test_provider_release_admission.py','test_provider_call_admission.py')) {
137137
$command = 'call "' + $vcvars + '" && python tests\' + $script + ' --compiler cl'
138138
& $env:ComSpec /d /c $command
139139
if ($LASTEXITCODE) { throw "Compatibility routing test failed: $script" }
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#pragma once
2+
3+
#include <cstddef>
4+
#include <mutex>
5+
#include <utility>
6+
7+
// One provider is shared by D3D12 and Vulkan. Transitions exclude all admitted
8+
// operations, but no metadata lock is held while running provider/native code.
9+
class ProviderCallAdmission
10+
{
11+
std::mutex _mutex;
12+
std::size_t _operations = 0;
13+
bool _transition = false;
14+
15+
public:
16+
class Lease
17+
{
18+
friend class ProviderCallAdmission;
19+
ProviderCallAdmission* _owner = nullptr;
20+
bool _transition = false;
21+
Lease(ProviderCallAdmission* owner, bool transition) : _owner(owner), _transition(transition) {}
22+
23+
public:
24+
Lease() = default;
25+
Lease(const Lease&) = delete;
26+
Lease& operator=(const Lease&) = delete;
27+
Lease(Lease&& other) noexcept : _owner(std::exchange(other._owner, nullptr)), _transition(other._transition) {}
28+
explicit operator bool() const { return _owner != nullptr; }
29+
~Lease()
30+
{
31+
if (!_owner)
32+
return;
33+
std::scoped_lock lock(_owner->_mutex);
34+
if (_transition)
35+
_owner->_transition = false;
36+
else
37+
--_owner->_operations;
38+
}
39+
};
40+
41+
Lease TryOperation()
42+
{
43+
std::scoped_lock lock(_mutex);
44+
if (_transition)
45+
return {};
46+
++_operations;
47+
return { this, false };
48+
}
49+
50+
Lease TryTransition()
51+
{
52+
std::scoped_lock lock(_mutex);
53+
if (_transition || _operations != 0)
54+
return {};
55+
_transition = true;
56+
return { this, true };
57+
}
58+
};

‎OptiScaler/framegen/nvngx/Nvngx_FG.cpp‎

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_Init(unsigned long long InApplicationId, const
230230
ID3D12Device* InDevice, const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo,
231231
NVSDK_NGX_Version InSDKVersion)
232232
{
233+
auto lease = _calls.TryTransition();
234+
if (!lease)
235+
return NVSDK_NGX_Result_FAIL_NotInitialized;
236+
233237
const auto lookup = lookupProvider();
234238
if (lookup.status == ProviderStatus::Pending)
235239
return NVSDK_NGX_Result_FAIL_NotInitialized;
@@ -245,6 +249,10 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_Init_Ext(unsigned long long InApplicationId, co
245249
ID3D12Device* InDevice, NVSDK_NGX_Version InSDKVersion,
246250
const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo)
247251
{
252+
auto lease = _calls.TryTransition();
253+
if (!lease)
254+
return NVSDK_NGX_Result_FAIL_NotInitialized;
255+
248256
const auto lookup = lookupProvider();
249257
if (lookup.status == ProviderStatus::Pending)
250258
return NVSDK_NGX_Result_FAIL_NotInitialized;
@@ -258,27 +266,21 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_Init_Ext(unsigned long long InApplicationId, co
258266

259267
NVSDK_NGX_Result Nvngx_FG::D3D12_Shutdown()
260268
{
261-
auto* provider = _provider.Peek();
262-
263-
if (!provider)
264-
return NVSDK_NGX_Result_Fail;
265-
266-
return provider->D3D12_Shutdown();
269+
return WithDx12Shutdown([&](auto closeProvider) { return closeProvider(nullptr); });
267270
}
268271

269272
NVSDK_NGX_Result Nvngx_FG::D3D12_Shutdown1(ID3D12Device* InDevice)
270273
{
271-
auto* provider = _provider.Peek();
272-
273-
if (!provider)
274-
return NVSDK_NGX_Result_Fail;
275-
276-
return provider->D3D12_Shutdown1(InDevice);
274+
return WithDx12Shutdown([&](auto closeProvider) { return closeProvider(InDevice); });
277275
}
278276

279277
NVSDK_NGX_Result Nvngx_FG::D3D12_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId,
280278
const NVSDK_NGX_Parameter* InParameters, size_t* OutSizeInBytes)
281279
{
280+
auto lease = _calls.TryOperation();
281+
if (!lease)
282+
return NVSDK_NGX_Result_FAIL_NotInitialized;
283+
282284
auto* provider = getProvider();
283285

284286
if (!provider)
@@ -290,6 +292,14 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_GetScratchBufferSize(NVSDK_NGX_Feature InFeatur
290292
NVSDK_NGX_Result Nvngx_FG::D3D12_CreateFeature(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_Feature InFeatureID,
291293
NVSDK_NGX_Parameter* InParameters, NVSDK_NGX_Handle** OutHandle)
292294
{
295+
if (!OutHandle)
296+
return NVSDK_NGX_Result_FAIL_InvalidParameter;
297+
*OutHandle = nullptr;
298+
299+
auto lease = _calls.TryOperation();
300+
if (!lease)
301+
return NVSDK_NGX_Result_FAIL_NotInitialized;
302+
293303
return CreateProviderHandle(_handles, OutHandle, Nvngx_FG_Handle { lastIdCreated++ + NVNGX_PROVIDER_ID_OFFSET },
294304
NVSDK_NGX_Result_Success, NVSDK_NGX_Result_FAIL_InvalidParameter, NVSDK_NGX_Result_Fail,
295305
[&](Nvngx_FG_Handle& handle)
@@ -304,6 +314,10 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_CreateFeature(ID3D12GraphicsCommandList* InCmdL
304314

305315
NVSDK_NGX_Result Nvngx_FG::D3D12_ReleaseFeature(NVSDK_NGX_Handle* InHandle)
306316
{
317+
auto lease = _calls.TryOperation();
318+
if (!lease)
319+
return NVSDK_NGX_Result_FAIL_NotInitialized;
320+
307321
auto* provider = getProvider();
308322

309323
if (!provider)
@@ -322,6 +336,10 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_GetFeatureRequirements(IDXGIAdapter* Adapter,
322336
const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo,
323337
NVSDK_NGX_FeatureRequirement* OutSupported)
324338
{
339+
auto lease = _calls.TryOperation();
340+
if (!lease)
341+
return NVSDK_NGX_Result_FAIL_NotInitialized;
342+
325343
auto* provider = getProvider();
326344

327345
if (!provider)
@@ -335,6 +353,10 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCm
335353
NVSDK_NGX_Parameter* InParameters,
336354
PFN_NVSDK_NGX_ProgressCallback InCallback)
337355
{
356+
auto lease = _calls.TryOperation();
357+
if (!lease)
358+
return NVSDK_NGX_Result_FAIL_NotInitialized;
359+
338360
auto* provider = getProvider();
339361

340362
if (!provider)
@@ -404,6 +426,10 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCm
404426

405427
NVSDK_NGX_Result Nvngx_FG::D3D12_PopulateParameters_Impl(NVSDK_NGX_Parameter* InParameters)
406428
{
429+
auto lease = _calls.TryOperation();
430+
if (!lease)
431+
return NVSDK_NGX_Result_FAIL_NotInitialized;
432+
407433
auto* provider = getProvider();
408434

409435
if (!provider)
@@ -417,6 +443,10 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_Init(unsigned long long InApplicationId, const
417443
PFN_vkGetInstanceProcAddr InGIPA, PFN_vkGetDeviceProcAddr InGDPA,
418444
const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo, NVSDK_NGX_Version InSDKVersion)
419445
{
446+
auto lease = _calls.TryTransition();
447+
if (!lease)
448+
return NVSDK_NGX_Result_FAIL_NotInitialized;
449+
420450
const auto lookup = lookupProvider();
421451
if (lookup.status == ProviderStatus::Pending)
422452
return NVSDK_NGX_Result_FAIL_NotInitialized;
@@ -434,6 +464,10 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_Init_Ext(unsigned long long InApplicationId, c
434464
NVSDK_NGX_Version InSDKVersion,
435465
const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo)
436466
{
467+
auto lease = _calls.TryTransition();
468+
if (!lease)
469+
return NVSDK_NGX_Result_FAIL_NotInitialized;
470+
437471
const auto lookup = lookupProvider();
438472
if (lookup.status == ProviderStatus::Pending)
439473
return NVSDK_NGX_Result_FAIL_NotInitialized;
@@ -452,6 +486,10 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_Init_Ext2(unsigned long long InApplicationId,
452486
NVSDK_NGX_Version InSDKVersion,
453487
const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo)
454488
{
489+
auto lease = _calls.TryTransition();
490+
if (!lease)
491+
return NVSDK_NGX_Result_FAIL_NotInitialized;
492+
455493
const auto lookup = lookupProvider();
456494
if (lookup.status == ProviderStatus::Pending)
457495
return NVSDK_NGX_Result_FAIL_NotInitialized;
@@ -466,27 +504,21 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_Init_Ext2(unsigned long long InApplicationId,
466504

467505
NVSDK_NGX_Result Nvngx_FG::VULKAN_Shutdown()
468506
{
469-
auto* provider = _provider.Peek();
470-
471-
if (!provider)
472-
return NVSDK_NGX_Result_Fail;
473-
474-
return provider->VULKAN_Shutdown();
507+
return WithVulkanShutdown([&](auto closeProvider) { return closeProvider(nullptr); });
475508
}
476509

477510
NVSDK_NGX_Result Nvngx_FG::VULKAN_Shutdown1(VkDevice InDevice)
478511
{
479-
auto* provider = _provider.Peek();
480-
481-
if (!provider)
482-
return NVSDK_NGX_Result_Fail;
483-
484-
return provider->VULKAN_Shutdown1(InDevice);
512+
return WithVulkanShutdown([&](auto closeProvider) { return closeProvider(InDevice); });
485513
}
486514

487515
NVSDK_NGX_Result Nvngx_FG::VULKAN_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId,
488516
const NVSDK_NGX_Parameter* InParameters, size_t* OutSizeInBytes)
489517
{
518+
auto lease = _calls.TryOperation();
519+
if (!lease)
520+
return NVSDK_NGX_Result_FAIL_NotInitialized;
521+
490522
auto* provider = getProvider();
491523

492524
if (!provider)
@@ -498,6 +530,14 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_GetScratchBufferSize(NVSDK_NGX_Feature InFeatu
498530
NVSDK_NGX_Result Nvngx_FG::VULKAN_CreateFeature(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Feature InFeatureID,
499531
NVSDK_NGX_Parameter* InParameters, NVSDK_NGX_Handle** OutHandle)
500532
{
533+
if (!OutHandle)
534+
return NVSDK_NGX_Result_FAIL_InvalidParameter;
535+
*OutHandle = nullptr;
536+
537+
auto lease = _calls.TryOperation();
538+
if (!lease)
539+
return NVSDK_NGX_Result_FAIL_NotInitialized;
540+
501541
return CreateProviderHandle(_handles, OutHandle, Nvngx_FG_Handle { lastIdCreated++ + NVNGX_PROVIDER_ID_OFFSET },
502542
NVSDK_NGX_Result_Success, NVSDK_NGX_Result_FAIL_InvalidParameter, NVSDK_NGX_Result_Fail,
503543
[&](Nvngx_FG_Handle& handle)
@@ -514,6 +554,14 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_CreateFeature1(VkDevice InDevice, VkCommandBuf
514554
NVSDK_NGX_Feature InFeatureID, NVSDK_NGX_Parameter* InParameters,
515555
NVSDK_NGX_Handle** OutHandle)
516556
{
557+
if (!OutHandle)
558+
return NVSDK_NGX_Result_FAIL_InvalidParameter;
559+
*OutHandle = nullptr;
560+
561+
auto lease = _calls.TryOperation();
562+
if (!lease)
563+
return NVSDK_NGX_Result_FAIL_NotInitialized;
564+
517565
return CreateProviderHandle(_handles, OutHandle, Nvngx_FG_Handle { lastIdCreated++ + NVNGX_PROVIDER_ID_OFFSET },
518566
NVSDK_NGX_Result_Success, NVSDK_NGX_Result_FAIL_InvalidParameter, NVSDK_NGX_Result_Fail,
519567
[&](Nvngx_FG_Handle& handle)
@@ -528,6 +576,10 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_CreateFeature1(VkDevice InDevice, VkCommandBuf
528576

529577
NVSDK_NGX_Result Nvngx_FG::VULKAN_ReleaseFeature(NVSDK_NGX_Handle* InHandle)
530578
{
579+
auto lease = _calls.TryOperation();
580+
if (!lease)
581+
return NVSDK_NGX_Result_FAIL_NotInitialized;
582+
531583
auto* provider = getProvider();
532584

533585
if (!provider)
@@ -547,6 +599,10 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_GetFeatureRequirements(const VkInstance Instan
547599
const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo,
548600
NVSDK_NGX_FeatureRequirement* OutSupported)
549601
{
602+
auto lease = _calls.TryOperation();
603+
if (!lease)
604+
return NVSDK_NGX_Result_FAIL_NotInitialized;
605+
550606
auto* provider = getProvider();
551607

552608
if (!provider)
@@ -559,6 +615,10 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_EvaluateFeature(VkCommandBuffer InCmdList, con
559615
NVSDK_NGX_Parameter* InParameters,
560616
PFN_NVSDK_NGX_ProgressCallback InCallback)
561617
{
618+
auto lease = _calls.TryOperation();
619+
if (!lease)
620+
return NVSDK_NGX_Result_FAIL_NotInitialized;
621+
562622
auto* provider = getProvider();
563623

564624
if (!provider)
@@ -579,6 +639,10 @@ NVSDK_NGX_Result Nvngx_FG::VULKAN_EvaluateFeature(VkCommandBuffer InCmdList, con
579639

580640
NVSDK_NGX_Result Nvngx_FG::VULKAN_PopulateParameters_Impl(NVSDK_NGX_Parameter* InParameters)
581641
{
642+
auto lease = _calls.TryOperation();
643+
if (!lease)
644+
return NVSDK_NGX_Result_FAIL_NotInitialized;
645+
582646
auto* provider = getProvider();
583647

584648
if (!provider)

‎OptiScaler/framegen/nvngx/Nvngx_FG.h‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "IFGNvngx.h"
99
#include <framegen/ProviderHandleRegistry.h>
1010
#include <framegen/ProviderPublication.h>
11+
#include <framegen/ProviderCallAdmission.h>
1112

1213
class Nvngx_FG
1314
{
@@ -23,13 +24,46 @@ class Nvngx_FG
2324
static inline std::atomic_uint32_t lastIdCreated = 0;
2425
static inline ProviderHandleRegistry<Nvngx_FG_Handle> _handles;
2526
static inline ProviderPublication<IFGNvngx> _provider;
27+
static inline ProviderCallAdmission _calls;
2628
static inline std::unique_ptr<HudCopy_Dx12> _hudCopy;
2729

2830
static std::unique_ptr<IFGNvngx> createProvider();
2931
static ProviderLookup<IFGNvngx> lookupProvider();
3032
static IFGNvngx* getProvider();
3133

3234
public:
35+
// The exported API holds this admission through native shutdown, provider
36+
// shutdown and local cleanup. A rejected transition changes none of them.
37+
template <typename Callback> static NVSDK_NGX_Result WithDx12Shutdown(Callback&& callback)
38+
{
39+
auto lease = _calls.TryTransition();
40+
if (!lease)
41+
return NVSDK_NGX_Result_FAIL_NotInitialized;
42+
return std::forward<Callback>(callback)(
43+
[](ID3D12Device* device)
44+
{
45+
auto* provider = _provider.Peek();
46+
if (!provider || !provider->isDx12Available())
47+
return NVSDK_NGX_Result_Success;
48+
return device ? provider->D3D12_Shutdown1(device) : provider->D3D12_Shutdown();
49+
});
50+
}
51+
52+
template <typename Callback> static NVSDK_NGX_Result WithVulkanShutdown(Callback&& callback)
53+
{
54+
auto lease = _calls.TryTransition();
55+
if (!lease)
56+
return NVSDK_NGX_Result_FAIL_NotInitialized;
57+
return std::forward<Callback>(callback)(
58+
[](VkDevice device)
59+
{
60+
auto* provider = _provider.Peek();
61+
if (!provider || !provider->isVulkanAvailable())
62+
return NVSDK_NGX_Result_Success;
63+
return device ? provider->VULKAN_Shutdown1(device) : provider->VULKAN_Shutdown();
64+
});
65+
}
66+
3367
static std::optional<unsigned int> GetHandleId(const NVSDK_NGX_Handle* handle)
3468
{
3569
return _handles.GetIdentity(handle, [](const Nvngx_FG_Handle& value) { return value.id; });

0 commit comments

Comments
 (0)