Files
UnrealEngine/Engine/Source/Runtime/MaterialShaderQualitySettings/Private/MaterialShaderQualitySettings.cpp
2025-05-18 13:04:45 +08:00

171 lines
6.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MaterialShaderQualitySettings.h"
#include "UObject/Package.h"
#include "ShaderPlatformQualitySettings.h"
#include "Misc/SecureHash.h"
#include "RHI.h"
#include "Interfaces/ITargetPlatform.h"
#include "Interfaces/ITargetPlatformManagerModule.h"
#include "DataDrivenShaderPlatformInfo.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(MaterialShaderQualitySettings)
UMaterialShaderQualitySettings* UMaterialShaderQualitySettings::RenderQualitySingleton = nullptr;
UMaterialShaderQualitySettings::UMaterialShaderQualitySettings(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
UMaterialShaderQualitySettings* UMaterialShaderQualitySettings::Get()
{
if( RenderQualitySingleton == nullptr )
{
static const TCHAR* SettingsContainerName = TEXT("MaterialShaderQualitySettingsContainer");
RenderQualitySingleton = FindObject<UMaterialShaderQualitySettings>(GetTransientPackage(), SettingsContainerName);
if (RenderQualitySingleton == nullptr)
{
RenderQualitySingleton = NewObject<UMaterialShaderQualitySettings>(GetTransientPackage(), UMaterialShaderQualitySettings::StaticClass(), SettingsContainerName);
RenderQualitySingleton->AddToRoot();
}
}
return RenderQualitySingleton;
}
#if WITH_EDITOR
const FName& UMaterialShaderQualitySettings::GetPreviewPlatform()
{
return PreviewPlatformName;
}
void UMaterialShaderQualitySettings::SetPreviewPlatform(FName PlatformName)
{
TObjectPtr<UShaderPlatformQualitySettings>* FoundPlatform = ForwardSettingMap.Find(PlatformName);
PreviewPlatformSettings = FoundPlatform == nullptr ? nullptr : FoundPlatform->Get();
PreviewPlatformName = PlatformName;
}
#endif
UShaderPlatformQualitySettings* UMaterialShaderQualitySettings::GetOrCreatePlatformSettings(FName ShaderPlatformName)
{
auto* PlatformSettings = ForwardSettingMap.Find(ShaderPlatformName);
if (PlatformSettings == nullptr)
{
FString ObjectName("ForwardShadingQuality_");
ShaderPlatformName.AppendString(ObjectName);
auto* ForwardQualitySettings = FindObject<UShaderPlatformQualitySettings>(this, *ObjectName);
if (ForwardQualitySettings == nullptr)
{
FName ForwardSettingsName(*ObjectName);
ForwardQualitySettings = NewObject<UShaderPlatformQualitySettings>(this, UShaderPlatformQualitySettings::StaticClass(), FName(*ObjectName));
// if we aren't running in the editor, then we will only want to use our own settings
#if WITH_EDITOR
ITargetPlatform* TargetPlatform = GetTargetPlatformManager()->FindTargetPlatformWithSupport(TEXT("ShaderFormat"), ShaderPlatformName);
ForwardQualitySettings->ConfigPlatformName = TargetPlatform ? TargetPlatform->IniPlatformName() : FString();
#endif
ForwardQualitySettings->LoadConfig();
}
return ForwardSettingMap.Add(ShaderPlatformName, ForwardQualitySettings);
}
return *PlatformSettings;
}
static const FName GetPlatformNameFromShaderPlatform(EShaderPlatform Platform)
{
return LegacyShaderPlatformToShaderFormat(Platform);
}
bool UMaterialShaderQualitySettings::HasPlatformQualitySettings(EShaderPlatform ShaderPlatform, EMaterialQualityLevel::Type QualityLevel)
{
const UShaderPlatformQualitySettings* PlatformShaderPlatformQualitySettings = GetShaderPlatformQualitySettings(ShaderPlatform);
const FMaterialQualityOverrides& PlatFormQualityOverrides = PlatformShaderPlatformQualitySettings->GetQualityOverrides(QualityLevel);
return PlatFormQualityOverrides.bEnableOverride && PlatFormQualityOverrides.HasAnyOverridesSet();
}
const UShaderPlatformQualitySettings* UMaterialShaderQualitySettings::GetShaderPlatformQualitySettings(EShaderPlatform ShaderPlatform)
{
#if WITH_EDITORONLY_DATA
// TODO: discuss this, in order to preview render quality settings we override the
// requested platform's settings.
// However we do not know if we are asking for the editor preview window (override able) or for thumbnails, cooking purposes etc.. (Must not override)
// The code below 'works' because desktop platforms do not cook for ES31 preview.
if (IsPCPlatform(ShaderPlatform) && GetMaxSupportedFeatureLevel(ShaderPlatform) <= ERHIFeatureLevel::ES3_1)
{
// Can check this cant be cooked by iterating through target platforms and shader formats to ensure it's not covered.
if (PreviewPlatformSettings != nullptr)
{
return PreviewPlatformSettings;
}
}
#endif
return GetShaderPlatformQualitySettings(GetPlatformNameFromShaderPlatform(ShaderPlatform));
}
UShaderPlatformQualitySettings* UMaterialShaderQualitySettings::GetShaderPlatformQualitySettings(FName PlatformName)
{
return GetOrCreatePlatformSettings(PlatformName);
}
//////////////////////////////////////////////////////////////////////////
UShaderPlatformQualitySettings::UShaderPlatformQualitySettings(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
// high quality overrides are always enabled by default
check(IsInGameThread());
GetQualityOverrides(EMaterialQualityLevel::High).bEnableOverride = true;
}
const FMaterialQualityOverrides& UShaderPlatformQualitySettings::GetQualityOverrides(EMaterialQualityLevel::Type QualityLevel) const
{
check(QualityLevel <= EMaterialQualityLevel::Num);
static const FMaterialQualityOverrides DefaultQualityOverrides;
return (QualityLevel < EMaterialQualityLevel::Num) ? QualityOverrides[(int32)QualityLevel] : DefaultQualityOverrides;
}
void UShaderPlatformQualitySettings::BuildHash(EMaterialQualityLevel::Type QualityLevel, FSHAHash& OutHash) const
{
FSHA1 Hash;
AppendToHashState(QualityLevel, Hash);
Hash.Final();
Hash.GetHash(&OutHash.Hash[0]);
}
void UShaderPlatformQualitySettings::AppendToHashState(EMaterialQualityLevel::Type QualityLevel, FSHA1& HashState) const
{
const FMaterialQualityOverrides& QualityLevelOverrides = GetQualityOverrides(QualityLevel);
HashState.Update((const uint8*)&QualityLevelOverrides, sizeof(QualityLevelOverrides));
}
//////////////////////////////////////////////////////////////////////////
bool FMaterialQualityOverrides::CanOverride(EShaderPlatform ShaderPlatform) const
{
// Only mobile renderer can lower the quality of a shader even without quality level nodes in the material (see TMobileBasePassPSPolicyParamType<>::ModifyCompilationEnvironmentForQualityLevel).
// Opt-in the platforms here that are going to use it.
return IsMobilePlatform(ShaderPlatform);
}
bool FMaterialQualityOverrides::HasAnyOverridesSet() const
{
static const FMaterialQualityOverrides DefaultOverrides;
return
MobileShadowQuality != DefaultOverrides.MobileShadowQuality
|| bForceDisableLMDirectionality != DefaultOverrides.bForceDisableLMDirectionality
|| bForceFullyRough != DefaultOverrides.bForceFullyRough
|| bForceNonMetal != DefaultOverrides.bForceNonMetal
|| bForceDisablePreintegratedGF != DefaultOverrides.bForceDisablePreintegratedGF
|| bDisableMaterialNormalCalculation != DefaultOverrides.bDisableMaterialNormalCalculation
|| bDiscardQualityDuringCook != DefaultOverrides.bDiscardQualityDuringCook;
}