|
1 | 1 | #pragma once |
2 | 2 | #include "SysUtils.h" |
3 | | - |
4 | 3 | #include "Config.h" |
5 | | - |
6 | 4 | #include <ankerl/unordered_dense.h> |
7 | 5 |
|
8 | 6 | // Use real NVNGX params encapsulated in custom one |
|
18 | 16 | #define LOG_PARAM(msg, ...) |
19 | 17 | #endif |
20 | 18 |
|
| 19 | +/** @brief Indicates the lifetime management required by an NGX parameter table. */ |
| 20 | +namespace NGX_AllocTypes |
| 21 | +{ |
| 22 | +// Key used to get/set enum from table |
| 23 | +constexpr std::string_view AllocKey = "OptiScaler.ParamAllocType"; |
| 24 | + |
| 25 | +constexpr uint32_t Unknown = 0; |
| 26 | +// Standard behavior in modern DLSS. Created with NGX Allocate(). Freed with Destroy(). |
| 27 | +constexpr uint32_t NVDynamic = 1; |
| 28 | +// Legacy DLSS. Lifetime managed internally by the SDK. |
| 29 | +constexpr uint32_t NVPersistent = 2; |
| 30 | +// OptiScaler implementation used internally with new/delete. |
| 31 | +constexpr uint32_t InternDynamic = 3; |
| 32 | +// OptiScaler implementation for legacy applications. Must maintain a persistent instance |
| 33 | +// for the lifetime of the application. |
| 34 | +constexpr uint32_t InternPersistent = 4; |
| 35 | +} // namespace NGX_AllocTypes |
| 36 | + |
21 | 37 | /// @brief Calculates the resolution scaling ratio override based on the provided quality level and current |
22 | 38 | /// configuration. |
23 | 39 | /// @param input The performance quality value (e.g. Quality, Balanced, Performance). |
@@ -670,6 +686,15 @@ struct NVNGX_Parameters : public NVSDK_NGX_Parameter |
670 | 686 | { |
671 | 687 | std::string Name; |
672 | 688 |
|
| 689 | + NVNGX_Parameters(std::string_view name, bool isPersistent) : Name(name) |
| 690 | + { |
| 691 | + // Old flag used to indicate custom table. Obsolete? |
| 692 | + Set("OptiScaler", 1); |
| 693 | + // New tracking flag |
| 694 | + Set(NGX_AllocTypes::AllocKey.data(), |
| 695 | + isPersistent ? NGX_AllocTypes::InternPersistent : NGX_AllocTypes::InternDynamic); |
| 696 | + } |
| 697 | + |
673 | 698 | #ifdef ENABLE_ENCAPSULATED_PARAMS |
674 | 699 | NVSDK_NGX_Parameter* OriginalParam = nullptr; |
675 | 700 | #endif // ENABLE_ENCAPSULATED_PARAMS |
@@ -934,8 +959,16 @@ struct NVNGX_Parameters : public NVSDK_NGX_Parameter |
934 | 959 | void Reset() override |
935 | 960 | { |
936 | 961 | if (!m_values.empty()) |
| 962 | + { |
| 963 | + // Preserve usage type if set |
| 964 | + uint32_t allocType = NGX_AllocTypes::Unknown; |
| 965 | + NVSDK_NGX_Result result = Get(NGX_AllocTypes::AllocKey.data(), &allocType); |
937 | 966 | m_values.clear(); |
938 | 967 |
|
| 968 | + if (result != NVSDK_NGX_Result_Fail) |
| 969 | + Set(NGX_AllocTypes::AllocKey.data(), allocType); |
| 970 | + } |
| 971 | + |
939 | 972 | LOG_DEBUG("Start"); |
940 | 973 |
|
941 | 974 | InitNGXParameters(this); |
@@ -981,13 +1014,64 @@ struct NVNGX_Parameters : public NVSDK_NGX_Parameter |
981 | 1014 | } |
982 | 1015 | }; |
983 | 1016 |
|
984 | | -/// @brief Allocates and populates a new NGX param map. |
985 | | -inline static NVNGX_Parameters* GetNGXParameters(std::string InName) |
| 1017 | +/** |
| 1018 | + * @brief Allocates and populates a new custom NGX param map. The persistence flag indicates |
| 1019 | + * whether the table should be destroyed when NGX DestroyParameters() is used. |
| 1020 | + */ |
| 1021 | +inline static NVNGX_Parameters* GetNGXParameters(std::string_view name, bool isPersistent) |
986 | 1022 | { |
987 | | - auto params = new NVNGX_Parameters(); |
988 | | - params->Name = InName; |
| 1023 | + auto params = new NVNGX_Parameters(name, isPersistent); |
989 | 1024 | InitNGXParameters(params); |
990 | | - params->Set("OptiScaler", 1); |
991 | | - |
992 | 1025 | return params; |
993 | 1026 | } |
| 1027 | + |
| 1028 | +/** |
| 1029 | + * @brief Sets a custom tracking tag to indicate the memory management strategy required by |
| 1030 | + * the table, indicated by NGX_AllocTypes. |
| 1031 | + */ |
| 1032 | +inline static void SetNGXParamAllocType(NVSDK_NGX_Parameter& params, uint32_t allocType) |
| 1033 | +{ |
| 1034 | + params.Set(NGX_AllocTypes::AllocKey.data(), allocType); |
| 1035 | +} |
| 1036 | + |
| 1037 | +/** |
| 1038 | + * @brief Attempts to safely delete an NGX parameter table. Dynamically allocated NGX tables use the NGX API. |
| 1039 | + * OptiScaler tables use delete. Persistent tables are not freed. |
| 1040 | + */ |
| 1041 | +template <typename PFN_DestroyNGXParameters> |
| 1042 | +static inline bool TryDestroyNGXParameters(NVSDK_NGX_Parameter* InParameters, PFN_DestroyNGXParameters NVFree = nullptr) |
| 1043 | +{ |
| 1044 | + if (InParameters == nullptr) |
| 1045 | + return false; |
| 1046 | + |
| 1047 | + uint32_t allocType = NGX_AllocTypes::Unknown; |
| 1048 | + NVSDK_NGX_Result result = InParameters->Get(NGX_AllocTypes::AllocKey.data(), &allocType); |
| 1049 | + |
| 1050 | + // Key not set. Either a bug, or the client application called Reset() on the table before destroying. |
| 1051 | + // Derived type unknown if this happens. Not safe to delete. Leaking is the best option. |
| 1052 | + if (result == NVSDK_NGX_Result_Fail) |
| 1053 | + { |
| 1054 | + LOG_WARN("Destroy called on NGX table with unset alloc type. Leaking."); |
| 1055 | + return false; |
| 1056 | + } |
| 1057 | + |
| 1058 | + if (allocType == NGX_AllocTypes::NVDynamic) |
| 1059 | + { |
| 1060 | + if (NVFree != nullptr) |
| 1061 | + { |
| 1062 | + LOG_INFO("Calling NVFree"); |
| 1063 | + result = NVFree(InParameters); |
| 1064 | + LOG_INFO("Calling NVFree result: {0:X}", (UINT) result); |
| 1065 | + return true; |
| 1066 | + } |
| 1067 | + else |
| 1068 | + return false; |
| 1069 | + } |
| 1070 | + else if (allocType == NGX_AllocTypes::InternDynamic) |
| 1071 | + { |
| 1072 | + delete static_cast<NVNGX_Parameters*>(InParameters); |
| 1073 | + return true; |
| 1074 | + } |
| 1075 | + |
| 1076 | + return false; |
| 1077 | +} |
0 commit comments