XinJiangBBH_LBE/Plugins/StreamlineDeepDVC/Source/StreamlineDeepDVCBlueprint/Private/StreamlineLibaryDeepDVC.cpp

452 lines
14 KiB
C++

/*
* Copyright (c) 2022 - 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
* property and proprietary rights in and to this material, related
* documentation and any modifications thereto. Any use, reproduction,
* disclosure or distribution of this material and related documentation
* without an express license agreement from NVIDIA CORPORATION or
* its affiliates is strictly prohibited.
*/
#include "StreamlineLibraryDeepDVC.h"
#if WITH_STREAMLINE
#include "StreamlineLibrary.h"
#include "StreamlineCore.h"
#include "StreamlineRHI.h"
#include "StreamlineDeepDVC.h"
#include "StreamlineAPI.h"
#include "sl.h"
#include "sl_deepdvc.h"
#endif
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"
#ifdef __INTELLISENSE__
#define WITH_STREAMLINE 1
#endif
#define LOCTEXT_NAMESPACE "FStreamlineDeepDVCBlueprintModule"
DEFINE_LOG_CATEGORY_STATIC(LogStreamlineDeepDVCBlueprint, Log, All);
static const FName SetDeepDVCModeInvalidEnumValueError= FName("SetDeepDVCModeInvalidEnumValueError");
static const FName IsDeepDVCModeSupportedInvalidEnumValueError = FName("IsDeepDVCModeSupportedInvalidEnumValueError");
UStreamlineFeatureSupport UStreamlineLibraryDeepDVC::DeepDVCSupport = UStreamlineFeatureSupport::NotSupportedByPlatformAtBuildTime;
#if WITH_STREAMLINE
bool UStreamlineLibraryDeepDVC::bDeepDVCLibraryInitialized = false;
static bool ShowDeepDVCSDebugOnScreenMessages()
{
return true;
}
#if !UE_BUILD_SHIPPING
UStreamlineLibraryDeepDVC::FDLSSErrorState UStreamlineLibraryDeepDVC::DLSSErrorState;
FDelegateHandle UStreamlineLibraryDeepDVC::DeepDVCOnScreenMessagesDelegateHandle;
void UStreamlineLibraryDeepDVC::GetDeepDVCOnScreenMessages(TMultiMap<FCoreDelegates::EOnScreenMessageSeverity, FText>& OutMessages)
{
check(IsInGameThread());
// We need a valid DLSSSupport, so calling this here in case other UStreamlineLibraryDeepDVC functions which call TryInitStreamlineLibrary() haven't been called
if (!TryInitDeepDVCLibrary())
{
return;
}
}
#endif
#endif
bool UStreamlineLibraryDeepDVC::IsDeepDVCModeSupported(UStreamlineDeepDVCMode DeepDVCMode)
{
const UEnum* Enum = StaticEnum<UStreamlineDeepDVCMode>();
// UEnums are strongly typed, but then one can also cast a byte to an UEnum ...
if (Enum->IsValidEnumValue(int64(DeepDVCMode)) && (Enum->GetMaxEnumValue() != int64(DeepDVCMode)))
{
if (DeepDVCMode == UStreamlineDeepDVCMode::Off)
{
return true;
}
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("IsDeepDVCModeSupported should not be called before PostEngineInit"));
return false;
}
if (!IsDeepDVCSupported())
{
return false;
}
else
{
return true; // TODO
}
#else
return false;
#endif
}
else
{
#if !UE_BUILD_SHIPPING
FFrame::KismetExecutionMessage(*FString::Printf(
TEXT("IsDeepDVCModeSupported should not be called with an invalid DeepDVCMode enum value (%d) \"%s\""),
int64(DeepDVCMode), *StaticEnum<UStreamlineDeepDVCMode>()->GetDisplayNameTextByValue(int64(DeepDVCMode)).ToString()),
ELogVerbosity::Error, IsDeepDVCModeSupportedInvalidEnumValueError);
#endif
return false;
}
}
TArray<UStreamlineDeepDVCMode> UStreamlineLibraryDeepDVC::GetSupportedDeepDVCModes()
{
TArray<UStreamlineDeepDVCMode> SupportedQualityModes;
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("GetSupportedDeepDVCModes should not be called before PostEngineInit"));
return SupportedQualityModes;
}
#endif
{
const UEnum* Enum = StaticEnum<UStreamlineDeepDVCMode>();
for (int32 EnumIndex = 0; EnumIndex < Enum->NumEnums(); ++EnumIndex)
{
const int64 EnumValue = Enum->GetValueByIndex(EnumIndex);
if (EnumValue != Enum->GetMaxEnumValue())
{
const UStreamlineDeepDVCMode QualityMode = UStreamlineDeepDVCMode(EnumValue);
if (IsDeepDVCModeSupported(QualityMode))
{
SupportedQualityModes.Add(QualityMode);
}
}
}
}
return SupportedQualityModes;
}
bool UStreamlineLibraryDeepDVC::IsDeepDVCSupported()
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("IsDeepDVCSupported should not be called before PostEngineInit"));
return false;
}
return QueryDeepDVCSupport() == UStreamlineFeatureSupport::Supported;
#else
return false;
#endif
}
UStreamlineFeatureSupport UStreamlineLibraryDeepDVC::QueryDeepDVCSupport()
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("QueryDeepDVCSupport should not be called before PostEngineInit"));
return UStreamlineFeatureSupport::NotSupported;
}
#endif
return DeepDVCSupport;
}
#if WITH_STREAMLINE
static int32 DeepDVCModeIntCvarFromEnum(UStreamlineDeepDVCMode DeepDVCMode)
{
switch (DeepDVCMode)
{
case UStreamlineDeepDVCMode::Off:
return 0;
case UStreamlineDeepDVCMode::On:
return 1;
default:
checkf(false, TEXT("dear DeepDVC plugin developer, please support new enum type!"));
return 0;
}
}
static UStreamlineDeepDVCMode DeepDVCModeEnumFromIntCvar(int32 DeepDVCMode)
{
switch (DeepDVCMode)
{
case 0:
return UStreamlineDeepDVCMode::Off;
case 1:
return UStreamlineDeepDVCMode::On;
default:
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("Invalid r.Streamline.DeepDVC.Enable value %d"), DeepDVCMode);
return UStreamlineDeepDVCMode::Off;
}
}
#endif // WITH_STREAMLINE
void UStreamlineLibraryDeepDVC::SetDeepDVCMode(UStreamlineDeepDVCMode DeepDVCMode)
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("SetDeepDVCMode should not be called before PostEngineInit"));
return;
}
const UEnum* Enum = StaticEnum<UStreamlineDeepDVCMode>();
// UEnums are strongly typed, but then one can also cast a byte to an UEnum ...
if(Enum->IsValidEnumValue(int64(DeepDVCMode)) && (Enum->GetMaxEnumValue() != int64(DeepDVCMode)))
{
static auto CVarDeepDVCEnable = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.DeepDVC.Enable"));
if (CVarDeepDVCEnable)
{
CVarDeepDVCEnable->SetWithCurrentPriority(DeepDVCModeIntCvarFromEnum(DeepDVCMode));
}
if (DeepDVCMode != UStreamlineDeepDVCMode::Off)
{
#if !UE_BUILD_SHIPPING
check(IsInGameThread());
DLSSErrorState.bIsDeepDVCModeUnsupported = !IsDeepDVCModeSupported(DeepDVCMode);
DLSSErrorState.InvalidDeepDVCMode = DeepDVCMode;
#endif
}
}
else
{
#if !UE_BUILD_SHIPPING
FFrame::KismetExecutionMessage(*FString::Printf(
TEXT("SetDeepDVCMode should not be called with an invalid DeepDVCMode enum value (%d) \"%s\""),
int64(DeepDVCMode), *StaticEnum<UStreamlineDeepDVCMode>()->GetDisplayNameTextByValue(int64(DeepDVCMode)).ToString()),
ELogVerbosity::Error, SetDeepDVCModeInvalidEnumValueError);
#endif
}
#endif // WITH_STREAMLINE
}
UStreamlineDeepDVCMode UStreamlineLibraryDeepDVC::GetDeepDVCMode()
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("GetDeepDVCMode should not be called before PostEngineInit"));
return UStreamlineDeepDVCMode::Off;
}
static const auto CVarDeepDVCEnable = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.DeepDVC.Enable"));
if (CVarDeepDVCEnable != nullptr)
{
return DeepDVCModeEnumFromIntCvar(CVarDeepDVCEnable->GetInt());
}
#endif
return UStreamlineDeepDVCMode::Off;
}
UStreamlineDeepDVCMode UStreamlineLibraryDeepDVC::GetDefaultDeepDVCMode()
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("GetDefaultDeepDVCMode should not be called before PostEngineInit"));
return UStreamlineDeepDVCMode::Off;
}
#endif
if (UStreamlineLibraryDeepDVC::IsDeepDVCSupported())
{
return UStreamlineDeepDVCMode::Off;
}
else
{
return UStreamlineDeepDVCMode::Off;
}
}
STREAMLINEDEEPDVCBLUEPRINT_API void UStreamlineLibraryDeepDVC::SetDeepDVCIntensity(float Intensity)
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("SetDeepDVCIntensity should not be called before PostEngineInit"));
return ;
}
static const auto CVarDeepDVCIntensity = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.DeepDVC.Intensity"));
if (CVarDeepDVCIntensity)
{
// Quantize here so we can have snap the value to 0, which downstream is used to turn off the DeepDVC implicitely
// CVarDeepDVCSaturationBoost->Set(..., ECVF_SetByCommandline) internally uses Set(*FString::Printf(TEXT("%g"), InValue),...); which doesn't snap to 0
CVarDeepDVCIntensity->Set(*FString::Printf(TEXT("%2.2f"), Intensity), ECVF_SetByCommandline);
}
#endif
}
STREAMLINEDEEPDVCBLUEPRINT_API float UStreamlineLibraryDeepDVC::GetDeepDVCIntensity()
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("GetDeepDVCIntensity should not be called before PostEngineInit"));
return 0.0f;
}
static const auto CVarDeepDVCIntensity = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.DeepDVC.Intensity"));
if (CVarDeepDVCIntensity)
{
return CVarDeepDVCIntensity->GetFloat();
}
#endif
return 0.0f;
}
STREAMLINEDEEPDVCBLUEPRINT_API void UStreamlineLibraryDeepDVC::SetDeepDVCSaturationBoost(float SaturationBoost)
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("SetDeepDVCSaturationBoost should not be called before PostEngineInit"));
return;
}
static const auto CVarDeepDVCSaturationBoost = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.DeepDVC.SaturationBoost"));
if (CVarDeepDVCSaturationBoost)
{
// Quantize here so we can have snap the value to 0, which is nice because hitting 0 is useful
// CVarDeepDVCSaturationBoost->Set(..., ECVF_SetByCommandline) internally uses Set(*FString::Printf(TEXT("%g"), InValue),...); which doesn't snap to 0
CVarDeepDVCSaturationBoost->Set(*FString::Printf(TEXT("%2.2f"), SaturationBoost), ECVF_SetByCommandline);
}
#endif
}
STREAMLINEDEEPDVCBLUEPRINT_API float UStreamlineLibraryDeepDVC::GetDeepDVCSaturationBoost()
{
#if WITH_STREAMLINE
if (!TryInitDeepDVCLibrary())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Error, TEXT("GetDeepDVCSaturationBoost should not be called before PostEngineInit"));
return 0.0f;
}
static const auto CVarDeepDVCSaturationBoost = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.DeepDVC.SaturationBoost"));
if (CVarDeepDVCSaturationBoost)
{
return CVarDeepDVCSaturationBoost->GetFloat();
}
#endif
return 0.0f;
}
#if WITH_STREAMLINE
// Delayed initialization, which allows this module to be available early so blueprints can be loaded before DLSS is available in PostEngineInit
bool UStreamlineLibraryDeepDVC::TryInitDeepDVCLibrary()
{
if (bDeepDVCLibraryInitialized)
{
// TODO
return true;
}
// Register this before we bail out so we can show error messages
#if !UE_BUILD_SHIPPING
if (!DeepDVCOnScreenMessagesDelegateHandle.IsValid())
{
DeepDVCOnScreenMessagesDelegateHandle = FCoreDelegates::OnGetOnScreenMessages.AddStatic(&GetDeepDVCOnScreenMessages);
}
#endif
if (IsStreamlineSupported())
{
if (GetPlatformStreamlineRHI()->IsDeepDVCSupportedByRHI())
{
DeepDVCSupport = ToUStreamlineFeatureSupport(QueryStreamlineDeepDVCSupport());
}
else
{
DeepDVCSupport = UStreamlineFeatureSupport::NotSupportedByRHI;
}
}
else
{
if (GetPlatformStreamlineSupport() == EStreamlineSupport::NotSupportedIncompatibleRHI)
{
DeepDVCSupport = UStreamlineFeatureSupport::NotSupportedByRHI;
}
else
{
DeepDVCSupport = UStreamlineFeatureSupport::NotSupported;
}
}
bDeepDVCLibraryInitialized = true;
return true;
}
#endif // WITH_STREAMLINE
void UStreamlineLibraryDeepDVC::Startup()
{
#if WITH_STREAMLINE
// This initialization will likely not succeed unless this module has been moved to PostEngineInit, and that's ok
UStreamlineLibraryDeepDVC::TryInitDeepDVCLibrary();
UStreamlineLibrary::RegisterFeatureSupport(UStreamlineFeature::DeepDVC, UStreamlineLibraryDeepDVC::QueryDeepDVCSupport());
#else
UE_LOG(LogStreamlineDeepDVCBlueprint, Log, TEXT("Streamline is not supported on this platform at build time. The Streamline Blueprint library however is supported and stubbed out to ignore any calls to enable DLSS-G and will always return UStreamlineDeepDVCSupport::NotSupportedByPlatformAtBuildTime, regardless of the underlying hardware. This can be used to e.g. to turn off DLSS-G related UI elements."));
UStreamlineLibraryDeepDVC::DeepDVCSupport = UStreamlineFeatureSupport::NotSupportedByPlatformAtBuildTime;
#endif
}
void UStreamlineLibraryDeepDVC::Shutdown()
{
#if WITH_STREAMLINE && !UE_BUILD_SHIPPING
if (UStreamlineLibraryDeepDVC::DeepDVCOnScreenMessagesDelegateHandle.IsValid())
{
FCoreDelegates::OnGetOnScreenMessages.Remove(UStreamlineLibraryDeepDVC::DeepDVCOnScreenMessagesDelegateHandle);
UStreamlineLibraryDeepDVC::DeepDVCOnScreenMessagesDelegateHandle.Reset();
}
#endif
}
void FStreamlineLibraryDeepDVCBlueprintModule::StartupModule()
{
auto CVarInitializePlugin = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.InitializePlugin"));
if (CVarInitializePlugin && !CVarInitializePlugin->GetBool())
{
UE_LOG(LogStreamlineDeepDVCBlueprint, Log, TEXT("Initialization of StreamlineBlueprint is disabled."));
return;
}
UStreamlineLibraryDeepDVC::Startup();
}
void FStreamlineLibraryDeepDVCBlueprintModule::ShutdownModule()
{
auto CVarInitializePlugin = IConsoleManager::Get().FindConsoleVariable(TEXT("r.Streamline.InitializePlugin"));
if (CVarInitializePlugin && !CVarInitializePlugin->GetBool())
{
return;
}
UStreamlineLibraryDeepDVC::Shutdown();
}
IMPLEMENT_MODULE(FStreamlineLibraryDeepDVCBlueprintModule, StreamlineDeepDVCBlueprint)
#undef LOCTEXT_NAMESPACE