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

605 lines
24 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "DataDrivenShaderPlatformInfo.h"
#include "Misc/ConfigCacheIni.h"
#include "Misc/DataDrivenPlatformInfoRegistry.h"
#include "Misc/CommandLine.h"
#include "RHI.h"
#include "RHIStrings.h"
#if WITH_EDITOR
#include "Internationalization/Text.h"
#endif
const FName LANGUAGE_D3D("D3D");
const FName LANGUAGE_Metal("Metal");
const FName LANGUAGE_OpenGL("OpenGL");
const FName LANGUAGE_Vulkan("Vulkan");
const FName LANGUAGE_Sony("Sony");
const FName LANGUAGE_Nintendo("Nintendo");
FGenericDataDrivenShaderPlatformInfo FGenericDataDrivenShaderPlatformInfo::Infos[SP_NumPlatforms];
static TMap<FName, EShaderPlatform> PlatformNameToShaderPlatformMap;
#if WITH_EDITOR
struct FDataDrivenShaderPlatformInfoEditorOnly
{
FText FriendlyName;
EShaderPlatform PreviewShaderPlatformParent = SP_NumPlatforms;
uint32 bCanUsePreviewPlatformForMaterialValidation : 1;
};
static FDataDrivenShaderPlatformInfoEditorOnly DataDrivenShaderPlatformInfoEditorOnlyInfos[SP_NumPlatforms];
TMap<FString, TFunction<bool(const FStaticShaderPlatform Platform)>> FGenericDataDrivenShaderPlatformInfo::PropertyToShaderPlatformFunctionMap;
#endif
EShaderPlatform ParseShaderPlatform(const TCHAR* String)
{
for (int i = 0; i < (int)EShaderPlatform::SP_NumPlatforms; ++i)
{
if (LexToString((EShaderPlatform)i, false).Equals(String, ESearchCase::IgnoreCase))
{
return (EShaderPlatform)i;
}
}
return SP_NumPlatforms;
}
// Gets a string from a section, or empty string if it didn't exist
static inline FString GetSectionString(const FConfigSection& Section, FName Key)
{
const FConfigValue* Value = Section.Find(Key);
return Value ? Value->GetValue() : FString();
}
// Gets a string from a section, or default string if it didn't exist
static inline FName GetSectionString(const FConfigSection& Section, FName Key, FName DefaultValue)
{
const FConfigValue* Value = Section.Find(Key);
return Value ? *Value->GetValue() : DefaultValue;
}
// Gets a bool from a section. It returns the original value if the setting does not exist
static inline bool GetSectionBool(const FConfigSection& Section, FName Key, bool OriginalValue)
{
const FConfigValue* ConfigValue = Section.Find(Key);
if (ConfigValue != nullptr)
{
return FCString::ToBool(*ConfigValue->GetValue());
}
else
{
return OriginalValue;
}
}
// Gets an integer from a section. It returns the original value if the setting does not exist
static inline uint32 GetSectionUint(const FConfigSection& Section, FName Key, uint32 OriginalValue)
{
const FConfigValue* ConfigValue = Section.Find(Key);
if (ConfigValue != nullptr)
{
return (uint32)FCString::Atoi(*ConfigValue->GetValue());
}
else
{
return OriginalValue;
}
}
// Gets an integer from a section. It returns the original value if the setting does not exist
static inline uint32 GetSectionFeatureSupport(const FConfigSection& Section, FName Key, uint32 OriginalValue)
{
const FConfigValue* ConfigValue = Section.Find(Key);
if (ConfigValue != nullptr)
{
FString Value = ConfigValue->GetValue();
if (Value == TEXT("Unsupported"))
{
return uint32(ERHIFeatureSupport::Unsupported);
}
if (Value == TEXT("RuntimeDependent"))
{
return uint32(ERHIFeatureSupport::RuntimeDependent);
}
else if (Value == TEXT("RuntimeGuaranteed"))
{
return uint32(ERHIFeatureSupport::RuntimeGuaranteed);
}
else
{
checkf(false, TEXT("Unknown ERHIFeatureSupport value \"%s\" for %s"), *Value, *Key.ToString());
}
}
return OriginalValue;
}
static inline uint32 GetSectionStaticShaderBindingLayoutSupport(const FConfigSection& Section, FName Key, uint32 OriginalValue)
{
const FConfigValue* ConfigValue = Section.Find(Key);
if (ConfigValue != nullptr)
{
FString Value = ConfigValue->GetValue();
if (Value == TEXT("Unsupported"))
{
return uint32(ERHIStaticShaderBindingLayoutSupport::Unsupported);
}
if (Value == TEXT("RayTracingOnly"))
{
return uint32(ERHIStaticShaderBindingLayoutSupport::RayTracingOnly);
}
else if (Value == TEXT("AllShaderTypes"))
{
return uint32(ERHIStaticShaderBindingLayoutSupport::AllShaderTypes);
}
else
{
checkf(false, TEXT("Unknown ERHIStaticShaderBindingLayoutSupport value \"%s\" for %s"), *Value, *Key.ToString());
}
}
return OriginalValue;
}
void FGenericDataDrivenShaderPlatformInfo::SetDefaultValues()
{
MaxFeatureLevel = ERHIFeatureLevel::Num;
bSupportsMSAA = true;
bSupportsUnrestrictedHalfFloatBuffers = true;
bSupportsDOFHybridScattering = true;
bSupportsHZBOcclusion = true;
bSupportsWaterIndirectDraw = true;
bSupportsAsyncPipelineCompilation = true;
bSupportsVertexShaderSRVs = true; // Explicitly overriden to false for ES 3.1 platforms via DDPI ini
bSupportsVertexShaderUAVs = uint32(ERHIFeatureSupport::Unsupported);
bSupportsTypedBufferSRVs = true;
bSupportsManualVertexFetch = true;
bSupportsVolumeTextureAtomics = true;
bSupportsClipDistance = true;
bSupportsShaderPipelines = true;
MaxSamplers = 16;
}
void FGenericDataDrivenShaderPlatformInfo::ParseDataDrivenShaderInfo(const FConfigSection& Section, uint32 Index)
{
FGenericDataDrivenShaderPlatformInfo& Info = Infos[Index];
Info.Language = GetSectionString(Section, "Language", Info.Language);
Info.ShaderFormat = GetSectionString(Section, "ShaderFormat", Info.ShaderFormat);
checkf(!Info.ShaderFormat.IsNone(), TEXT("Missing ShaderFormat for ShaderPlatform %s ShaderFormat %s"), *Info.Name.ToString(), *Info.ShaderFormat.ToString());
const FConfigValue* MaxFeatureLevelValue = Section.Find("MaxFeatureLevel");
if (MaxFeatureLevelValue)
{
GetFeatureLevelFromName(MaxFeatureLevelValue->GetValue(), Info.MaxFeatureLevel);
}
Info.ShaderPropertiesHash = 0;
FString ShaderPropertiesString = Info.Name.GetPlainNameString();
#define ADD_TO_PROPERTIES_STRING(SettingName, SettingValue) \
ShaderPropertiesString += TEXT(#SettingName); \
ShaderPropertiesString += FString::Printf(TEXT("_%d"), SettingValue);
#if WITH_EDITOR
#define ADD_PROPERTY_TO_SHADERPLATFORM_FUNCTIONMAP(SettingName, FunctionName) \
FGenericDataDrivenShaderPlatformInfo::PropertyToShaderPlatformFunctionMap.FindOrAdd(#SettingName) = &FunctionName;
#else
#define ADD_PROPERTY_TO_SHADERPLATFORM_FUNCTIONMAP(SettingName, FunctionName)
#endif
#define GET_SECTION_BOOL_HELPER(SettingName) \
Info.SettingName = GetSectionBool(Section, #SettingName, Info.SettingName); \
ADD_TO_PROPERTIES_STRING(SettingName, Info.SettingName)
#define GET_SECTION_INT_HELPER(SettingName) \
Info.SettingName = GetSectionUint(Section, #SettingName, Info.SettingName); \
ADD_TO_PROPERTIES_STRING(SettingName, Info.SettingName)
#define GET_SECTION_SUPPORT_HELPER(SettingName) \
Info.SettingName = GetSectionFeatureSupport(Section, #SettingName, Info.SettingName); \
ADD_TO_PROPERTIES_STRING(SettingName, Info.SettingName)
#define GET_SECTION_STATIC_SHADER_BINDING_LAYOUT_SUPPORT_HELPER(SettingName) \
Info.SettingName = GetSectionStaticShaderBindingLayoutSupport(Section, #SettingName, Info.SettingName); \
ADD_TO_PROPERTIES_STRING(SettingName, Info.SettingName)
// These properties will be exposed to the MaterialEditor that use the ShaderPlatformInfo Node
// If you remove/rename a property be sure to address this in UMaterialExpressionDataDrivenShaderPlatformInfoSwitch serialization
// If you add a property that you think needs to be exposed to materials, it is enough to just call the macro here with the property name and the function it will call
ADD_PROPERTY_TO_SHADERPLATFORM_FUNCTIONMAP(IsMobile, GetIsMobile);
ADD_PROPERTY_TO_SHADERPLATFORM_FUNCTIONMAP(IsPC, GetIsPC);
ADD_PROPERTY_TO_SHADERPLATFORM_FUNCTIONMAP(IsConsole, GetIsConsole);
GET_SECTION_BOOL_HELPER(bIsMobile);
GET_SECTION_BOOL_HELPER(bIsMetalMRT);
GET_SECTION_BOOL_HELPER(bIsPC);
GET_SECTION_BOOL_HELPER(bIsConsole);
GET_SECTION_BOOL_HELPER(bIsAndroidOpenGLES);
GET_SECTION_BOOL_HELPER(bSupportsDebugViewShaders);
GET_SECTION_BOOL_HELPER(bSupportsMobileMultiView);
GET_SECTION_BOOL_HELPER(bSupportsArrayTextureCompression);
GET_SECTION_BOOL_HELPER(bSupportsDistanceFields);
GET_SECTION_BOOL_HELPER(bSupportsDiaphragmDOF);
GET_SECTION_BOOL_HELPER(bSupportsRGBColorBuffer);
GET_SECTION_BOOL_HELPER(bSupportsPercentageCloserShadows);
GET_SECTION_BOOL_HELPER(bSupportsIndexBufferUAVs);
GET_SECTION_BOOL_HELPER(bSupportsInstancedStereo);
GET_SECTION_SUPPORT_HELPER(SupportsMultiViewport);
GET_SECTION_BOOL_HELPER(bSupportsMSAA);
GET_SECTION_BOOL_HELPER(bSupports4ComponentUAVReadWrite);
GET_SECTION_BOOL_HELPER(bSupportsShaderRootConstants);
GET_SECTION_BOOL_HELPER(bSupportsShaderBundleDispatch);
GET_SECTION_BOOL_HELPER(bSupportsRenderTargetWriteMask);
GET_SECTION_BOOL_HELPER(bSupportsRayTracing);
GET_SECTION_BOOL_HELPER(bSupportsRayTracingShaders);
GET_SECTION_BOOL_HELPER(bSupportsInlineRayTracing);
GET_SECTION_BOOL_HELPER(bInlineRayTracingRequiresBindless);
GET_SECTION_BOOL_HELPER(bSupportsRayTracingCallableShaders);
GET_SECTION_BOOL_HELPER(bSupportsRayTracingProceduralPrimitive);
GET_SECTION_BOOL_HELPER(bSupportsRayTracingTraversalStatistics);
GET_SECTION_BOOL_HELPER(bSupportsRayTracingIndirectInstanceData);
GET_SECTION_BOOL_HELPER(bSupportsPathTracing);
GET_SECTION_BOOL_HELPER(bSupportsShaderExecutionReordering);
GET_SECTION_BOOL_HELPER(bSupportsUnrestrictedHalfFloatBuffers)
GET_SECTION_BOOL_HELPER(bSupportsGPUScene);
GET_SECTION_BOOL_HELPER(bSupportsPrimitiveShaders);
GET_SECTION_BOOL_HELPER(bSupportsUInt64ImageAtomics);
GET_SECTION_BOOL_HELPER(bRequiresVendorExtensionsForAtomics);
GET_SECTION_BOOL_HELPER(bSupportsNanite);
GET_SECTION_BOOL_HELPER(bSupportsLumenGI);
GET_SECTION_BOOL_HELPER(bSupportsSSDIndirect);
GET_SECTION_BOOL_HELPER(bSupportsTemporalHistoryUpscale);
GET_SECTION_BOOL_HELPER(bSupportsRTIndexFromVS);
GET_SECTION_BOOL_HELPER(bSupportsIntrinsicWaveOnce);
GET_SECTION_BOOL_HELPER(bSupportsConservativeRasterization);
GET_SECTION_SUPPORT_HELPER(bSupportsWaveOperations);
GET_SECTION_BOOL_HELPER(bSupportsWavePermute);
GET_SECTION_INT_HELPER(MinimumWaveSize);
GET_SECTION_INT_HELPER(MaximumWaveSize);
GET_SECTION_BOOL_HELPER(bRequiresExplicit128bitRT);
GET_SECTION_BOOL_HELPER(bSupportsGen5TemporalAA);
GET_SECTION_BOOL_HELPER(bTargetsTiledGPU);
GET_SECTION_BOOL_HELPER(bNeedsOfflineCompiler);
GET_SECTION_BOOL_HELPER(bSupportsComputeFramework);
GET_SECTION_BOOL_HELPER(bSupportsAnisotropicMaterials);
GET_SECTION_BOOL_HELPER(bSupportsDualSourceBlending);
GET_SECTION_BOOL_HELPER(bRequiresGeneratePrevTransformBuffer);
GET_SECTION_BOOL_HELPER(bRequiresRenderTargetDuringRaster);
GET_SECTION_BOOL_HELPER(bRequiresDisableForwardLocalLights);
GET_SECTION_BOOL_HELPER(bCompileSignalProcessingPipeline);
GET_SECTION_BOOL_HELPER(bSupportsMeshShadersTier0);
GET_SECTION_BOOL_HELPER(bSupportsMeshShadersTier1);
GET_SECTION_BOOL_HELPER(bSupportsMeshShadersWithClipDistance);
GET_SECTION_INT_HELPER(MaxMeshShaderThreadGroupSize);
GET_SECTION_BOOL_HELPER(bRequiresUnwrappedMeshShaderArgs);
GET_SECTION_BOOL_HELPER(bSupportsPerPixelDBufferMask);
GET_SECTION_BOOL_HELPER(bIsHlslcc);
GET_SECTION_BOOL_HELPER(bSupportsDxc);
GET_SECTION_BOOL_HELPER(bSupportsVariableRateShading);
GET_SECTION_BOOL_HELPER(bIsSPIRV);
GET_SECTION_INT_HELPER(NumberOfComputeThreads);
GET_SECTION_BOOL_HELPER(bWaterUsesSimpleForwardShading);
GET_SECTION_BOOL_HELPER(bSupportsHairStrandGeometry);
GET_SECTION_BOOL_HELPER(bSupportsDOFHybridScattering);
GET_SECTION_BOOL_HELPER(bNeedsExtraMobileFrames);
GET_SECTION_BOOL_HELPER(bSupportsHZBOcclusion);
GET_SECTION_BOOL_HELPER(bSupportsWaterIndirectDraw);
GET_SECTION_BOOL_HELPER(bSupportsAsyncPipelineCompilation);
GET_SECTION_BOOL_HELPER(bSupportsVertexShaderSRVs);
GET_SECTION_SUPPORT_HELPER(bSupportsVertexShaderUAVs);
GET_SECTION_BOOL_HELPER(bSupportsTypedBufferSRVs);
GET_SECTION_BOOL_HELPER(bSupportsManualVertexFetch);
GET_SECTION_BOOL_HELPER(bRequiresReverseCullingOnMobile);
GET_SECTION_BOOL_HELPER(bOverrideFMaterial_NeedsGBufferEnabled);
GET_SECTION_BOOL_HELPER(bSupportsFFTBloom);
GET_SECTION_BOOL_HELPER(bSupportsVertexShaderLayer);
GET_SECTION_BOOL_HELPER(bSupportsBindless);
GET_SECTION_STATIC_SHADER_BINDING_LAYOUT_SUPPORT_HELPER(StaticShaderBindingLayoutSupport);
GET_SECTION_BOOL_HELPER(bSupportsVolumeTextureAtomics);
GET_SECTION_BOOL_HELPER(bSupportsROV);
GET_SECTION_BOOL_HELPER(bSupportsOIT);
GET_SECTION_SUPPORT_HELPER(bSupportsRealTypes);
GET_SECTION_INT_HELPER(EnablesHLSL2021ByDefault);
GET_SECTION_BOOL_HELPER(bSupportsSceneDataCompressedTransforms);
GET_SECTION_BOOL_HELPER(bSupportsSwapchainUAVs);
GET_SECTION_BOOL_HELPER(bSupportsClipDistance);
GET_SECTION_BOOL_HELPER(bSupportsNNEShaders);
GET_SECTION_BOOL_HELPER(bSupportsShaderPipelines);
GET_SECTION_BOOL_HELPER(bSupportsUniformBufferObjects);
GET_SECTION_BOOL_HELPER(bRequiresBindfulUtilityShaders);
GET_SECTION_INT_HELPER(MaxSamplers);
GET_SECTION_BOOL_HELPER(SupportsBarycentricsIntrinsics);
GET_SECTION_SUPPORT_HELPER(SupportsBarycentricsSemantic);
GET_SECTION_BOOL_HELPER(bSupportsWave64);
GET_SECTION_BOOL_HELPER(bSupportsIndependentSamplers);
GET_SECTION_BOOL_HELPER(bSupportsWorkGraphs);
GET_SECTION_BOOL_HELPER(bSupportsWorkGraphsTier1_1);
GET_SECTION_BOOL_HELPER(bSupportsDLSSShaders);
#undef GET_SECTION_BOOL_HELPER
#undef GET_SECTION_INT_HELPER
#undef GET_SECTION_SUPPORT_HELPER
#undef ADD_TO_PROPERTIES_STRING
#undef ADD_PROPERTY_TO_SHADERPLATFORM_FUNCTIONMAP
Info.ShaderPropertiesHash = GetTypeHash(ShaderPropertiesString);
#if WITH_EDITOR
FDataDrivenShaderPlatformInfoEditorOnly& EditorInfo = DataDrivenShaderPlatformInfoEditorOnlyInfos[Index];
FTextStringHelper::ReadFromBuffer(*GetSectionString(Section, FName("FriendlyName")), EditorInfo.FriendlyName);
EditorInfo.bCanUsePreviewPlatformForMaterialValidation = GetSectionBool(Section, "bCanUsePreviewPlatformForMaterialValidation", false);
#endif
}
void FGenericDataDrivenShaderPlatformInfo::Initialize()
{
static bool bInitialized = false;
if (bInitialized)
{
return;
}
PlatformNameToShaderPlatformMap.Empty();
// look for the standard DataDriven ini files
int32 NumDDInfoFiles = FDataDrivenPlatformInfoRegistry::GetNumDataDrivenIniFiles();
int32 CustomShaderPlatform = EShaderPlatform::SP_CUSTOM_PLATFORM_FIRST;
struct PlatformInfoAndPlatformEnum
{
FGenericDataDrivenShaderPlatformInfo Info;
EShaderPlatform ShaderPlatform;
};
for (int32 Index = 0; Index < NumDDInfoFiles; Index++)
{
FConfigFile IniFile;
FString PlatformName;
FDataDrivenPlatformInfoRegistry::LoadDataDrivenIniFile(Index, IniFile, PlatformName);
// now walk over the file, looking for ShaderPlatformInfo sections
for (const TPair<FString, FConfigSection>& Section : AsConst(IniFile))
{
if (Section.Key.StartsWith(TEXT("ShaderPlatform ")))
{
const FString& SectionName = Section.Key;
const FConfigSection& SectionSettings = Section.Value;
// get enum value for the string name
const EShaderPlatform ShaderPlatform = ParseShaderPlatform(*SectionName.Mid(15));
if (ShaderPlatform == SP_NumPlatforms)
{
#if DDPI_HAS_EXTENDED_PLATFORMINFO_DATA
const bool bIsEnabled = FDataDrivenPlatformInfoRegistry::GetPlatformInfo(PlatformName).bEnabledForUse;
#else
const bool bIsEnabled = true;
#endif
UE_CLOG(bIsEnabled, LogRHI, Warning, TEXT("Found an unknown shader platform %s in a DataDriven ini file"), *SectionName.Mid(15));
continue;
}
// at this point, we can start pulling information out
Infos[ShaderPlatform].Name = *SectionName.Mid(15);
Infos[ShaderPlatform].PlatformName = FName(*PlatformName);
PlatformNameToShaderPlatformMap.FindOrAdd(Infos[ShaderPlatform].Name) = ShaderPlatform;
ParseDataDrivenShaderInfo(SectionSettings, ShaderPlatform);
Infos[ShaderPlatform].bContainsValidPlatformInfo = true;
#if WITH_EDITOR
if (!FParse::Param(FCommandLine::Get(), TEXT("NoPreviewPlatforms")))
{
const FName& CurrentPlatformName = Infos[ShaderPlatform].Name;
for (const FPreviewPlatformMenuItem& Item : FDataDrivenPlatformInfoRegistry::GetAllPreviewPlatformMenuItems())
{
if (Item.ShaderPlatformToPreview == CurrentPlatformName)
{
const EShaderPlatform PreviewShaderPlatform = EShaderPlatform(CustomShaderPlatform++);
FGenericDataDrivenShaderPlatformInfo& PreviewInfo = Infos[PreviewShaderPlatform];
PreviewInfo.Name = Item.PreviewShaderPlatformName;
PreviewInfo.PlatformName = Infos[ShaderPlatform].PlatformName;
ParseDataDrivenShaderInfo(SectionSettings, PreviewShaderPlatform);
PreviewInfo.bIsPreviewPlatform = true;
PreviewInfo.bContainsValidPlatformInfo = true;
FDataDrivenShaderPlatformInfoEditorOnly& PreviewEditorInfo = DataDrivenShaderPlatformInfoEditorOnlyInfos[PreviewShaderPlatform];
PreviewEditorInfo.PreviewShaderPlatformParent = ShaderPlatform;
if (!Item.OptionalFriendlyNameOverride.IsEmpty())
{
PreviewEditorInfo.FriendlyName = Item.OptionalFriendlyNameOverride;
}
ERHIFeatureLevel::Type PreviewFeatureLevel = ERHIFeatureLevel::Num;
if (GetFeatureLevelFromName(Item.PreviewFeatureLevelName, PreviewFeatureLevel))
{
PreviewInfo.MaxFeatureLevel = PreviewFeatureLevel;
}
PlatformNameToShaderPlatformMap.FindOrAdd(PreviewInfo.Name) = PreviewShaderPlatform;
}
}
}
#endif
}
#if WITH_EDITOR
else if (Section.Key.StartsWith(TEXT("PreviewShaderPlatform ")))
{
const FString& SectionName = Section.Key;
const FConfigSection& SectionSettings = Section.Value;
const FString ParentShaderPlatformName = GetSectionString(SectionSettings, "ParentShaderPlatform");
const EShaderPlatform ParentShaderPlatform = ParseShaderPlatform(*ParentShaderPlatformName);
// get enum value for the string name
const EShaderPlatform ShaderPlatform = EShaderPlatform(CustomShaderPlatform++);
FGenericDataDrivenShaderPlatformInfo& Info = Infos[ShaderPlatform];
if (IsValid(ParentShaderPlatform))
{
const FGenericDataDrivenShaderPlatformInfo& ParentInfo = Infos[ParentShaderPlatform];
Info = ParentInfo;
}
Info.Name = *SectionName.Mid(22);
ParseDataDrivenShaderInfo(SectionSettings, ShaderPlatform);
Info.bContainsValidPlatformInfo = true;
Info.bIsPreviewPlatform = true;
ERHIFeatureLevel::Type PreviewFeatureLevel = ERHIFeatureLevel::Num;
if (GetFeatureLevelFromName(GetSectionString(SectionSettings, "PreviewFeatureLevel"), PreviewFeatureLevel))
{
Info.MaxFeatureLevel = PreviewFeatureLevel;
}
PlatformNameToShaderPlatformMap.FindOrAdd(Info.Name) = ShaderPlatform;
FDataDrivenShaderPlatformInfoEditorOnly& PreviewEditorInfo = DataDrivenShaderPlatformInfoEditorOnlyInfos[ShaderPlatform];
PreviewEditorInfo.PreviewShaderPlatformParent = ShaderPlatform;
}
#endif
}
}
bInitialized = true;
}
#if WITH_EDITOR
void FGenericDataDrivenShaderPlatformInfo::UpdatePreviewPlatforms()
{
for (int32 PlatformIndex=0; PlatformIndex < SP_NumPlatforms; PlatformIndex++)
{
const EShaderPlatform PreviewPlatform = EShaderPlatform(PlatformIndex);
if (IsValid(PreviewPlatform) && GetIsPreviewPlatform(PreviewPlatform))
{
const ERHIFeatureLevel::Type PreviewFeatureLevel = Infos[PreviewPlatform].MaxFeatureLevel;
const EShaderPlatform RuntimePlatform = GRHIGlobals.ShaderPlatformForFeatureLevel[PreviewFeatureLevel];
if (RuntimePlatform < SP_NumPlatforms)
{
FGenericDataDrivenShaderPlatformInfo& PreviewInfo = Infos[PreviewPlatform];
const FGenericDataDrivenShaderPlatformInfo& RuntimeInfo = Infos[RuntimePlatform];
#define PREVIEW_USE_RUNTIME_VALUE(SettingName) \
PreviewInfo.SettingName = RuntimeInfo.SettingName
#define PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(SettingName) \
PreviewInfo.SettingName &= RuntimeInfo.SettingName
#define PREVIEW_FORCE_SETTING(SettingName, Value) \
PreviewInfo.SettingName = (Value)
#define PREVIEW_FORCE_DISABLE(SettingName) \
PREVIEW_FORCE_SETTING(SettingName, false)
// Always inherit these core settings from the preview
PREVIEW_USE_RUNTIME_VALUE(ShaderFormat);
PREVIEW_USE_RUNTIME_VALUE(Language);
PREVIEW_USE_RUNTIME_VALUE(bIsHlslcc);
PREVIEW_USE_RUNTIME_VALUE(bSupportsDxc);
PREVIEW_USE_RUNTIME_VALUE(bIsSPIRV);
// Editor is always PC, never console and always supports debug view shaders
PREVIEW_FORCE_SETTING(bIsPC, true);
PREVIEW_FORCE_SETTING(bSupportsDebugViewShaders, true);
PREVIEW_FORCE_SETTING(bIsConsole, false);
// Support for stereo features requires extra consideration. The editor may not use the same technique as the preview platform,
// particularly MobileMultiView may be substituted by a fallback path. In order to avoid inundating real mobile platforms
// with the properties needed for the desktop MMV fallback path, override them here with the editor ones to make MMV preview possible
if (PreviewInfo.bSupportsMobileMultiView && !RuntimeInfo.bSupportsMobileMultiView)
{
PREVIEW_USE_RUNTIME_VALUE(bSupportsInstancedStereo);
PREVIEW_USE_RUNTIME_VALUE(bSupportsVertexShaderLayer);
}
else
{
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsInstancedStereo);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsVertexShaderLayer);
}
// Settings that should be kept true if the runtime also supports it.
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsNanite);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsLumenGI);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsPrimitiveShaders);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsUInt64ImageAtomics);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsGen5TemporalAA);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsMeshShadersTier0);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsMeshShadersTier1);
PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED(bSupportsMobileMultiView);
// Settings that need to match the runtime
PREVIEW_USE_RUNTIME_VALUE(bSupportsGPUScene);
PREVIEW_USE_RUNTIME_VALUE(MaxMeshShaderThreadGroupSize);
PREVIEW_USE_RUNTIME_VALUE(bSupportsSceneDataCompressedTransforms);
PREVIEW_USE_RUNTIME_VALUE(bSupportsVertexShaderSRVs);
PREVIEW_USE_RUNTIME_VALUE(bSupportsVertexShaderUAVs);
PREVIEW_USE_RUNTIME_VALUE(bSupportsTypedBufferSRVs);
PREVIEW_USE_RUNTIME_VALUE(bSupportsManualVertexFetch);
PREVIEW_USE_RUNTIME_VALUE(bSupportsRealTypes);
PREVIEW_USE_RUNTIME_VALUE(bSupportsUniformBufferObjects);
PREVIEW_USE_RUNTIME_VALUE(bRequiresBindfulUtilityShaders);
PREVIEW_USE_RUNTIME_VALUE(bSupportsInlineRayTracing);
PREVIEW_USE_RUNTIME_VALUE(bInlineRayTracingRequiresBindless);
PREVIEW_USE_RUNTIME_VALUE(bSupportsRayTracingShaders);
// Settings that will never be supported in preview
PREVIEW_FORCE_DISABLE(bSupportsShaderRootConstants);
PREVIEW_FORCE_DISABLE(bSupportsShaderBundleDispatch);
PREVIEW_FORCE_DISABLE(bSupportsRenderTargetWriteMask);
PREVIEW_FORCE_DISABLE(bSupportsIntrinsicWaveOnce);
PREVIEW_FORCE_DISABLE(bSupportsDOFHybridScattering);
PREVIEW_FORCE_DISABLE(bSupports4ComponentUAVReadWrite);
// Make sure we're marked valid
PreviewInfo.bContainsValidPlatformInfo = true;
// Seeing as we are merging the two shader platforms merge the hash key as well, this way
// any changes in the editor feature level shader platform will dirty the preview key.
PreviewInfo.ShaderPropertiesHash = HashCombine(PreviewInfo.ShaderPropertiesHash, RuntimeInfo.ShaderPropertiesHash);
#undef PREVIEW_FORCE_DISABLE
#undef PREVIEW_FORCE_SETTING
#undef PREVIEW_DISABLE_IF_RUNTIME_UNSUPPORTED
#undef PREVIEW_USE_RUNTIME_VALUE
}
}
}
}
FText FGenericDataDrivenShaderPlatformInfo::GetFriendlyName(const FStaticShaderPlatform Platform)
{
if (IsRunningCommandlet() || GUsingNullRHI)
{
return FText();
}
check(IsValid(Platform));
return DataDrivenShaderPlatformInfoEditorOnlyInfos[Platform].FriendlyName;
}
const EShaderPlatform FGenericDataDrivenShaderPlatformInfo::GetPreviewShaderPlatformParent(const FStaticShaderPlatform Platform)
{
check(IsValid(Platform));
return DataDrivenShaderPlatformInfoEditorOnlyInfos[Platform].PreviewShaderPlatformParent;
}
const bool FGenericDataDrivenShaderPlatformInfo::CanUseForMaterialValidation(const FStaticShaderPlatform Platform)
{
check(IsValid(Platform));
return DataDrivenShaderPlatformInfoEditorOnlyInfos[Platform].bCanUsePreviewPlatformForMaterialValidation || !Infos[Platform].bIsPreviewPlatform;
}
#endif // WITH_EDITOR
const EShaderPlatform FGenericDataDrivenShaderPlatformInfo::GetShaderPlatformFromName(const FName ShaderPlatformName)
{
if (EShaderPlatform* ShaderPlatform = PlatformNameToShaderPlatformMap.Find(ShaderPlatformName))
{
return *ShaderPlatform;
}
return SP_NumPlatforms;
}