// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "DataDrivenShaderPlatformInfo.h" #include "RHIGlobals.h" #include "ShaderPermutation.h" namespace UE::ShaderPermutationUtils { inline bool ShouldCompileWithWaveSize(const FShaderPermutationParameters& Parameters, int32 WaveSize) { if (WaveSize) { if (!RHISupportsWaveOperations(Parameters.Platform)) { return false; } if (WaveSize < int32(FDataDrivenShaderPlatformInfo::GetMinimumWaveSize(Parameters.Platform)) || WaveSize > int32(FDataDrivenShaderPlatformInfo::GetMaximumWaveSize(Parameters.Platform))) { return false; } } return true; } inline bool ShouldPrecacheWithWaveSize(const FShaderPermutationParameters& Parameters, int32 WaveSize) { if (WaveSize) { if (WaveSize < GRHIGlobals.MinimumWaveSize || WaveSize > GRHIGlobals.MaximumWaveSize) { return false; } } return true; } template void FormatPermutationParameter(const typename TDimension::Type& E, FString& OutString, bool bFullNames, const TCHAR* Prefix); FORCEINLINE void FormatPermutationDomain(const TShaderPermutationDomain<>& InShaderPermutationDomain, FString& OutString, bool bFullNames, const TCHAR* Prefix) { // Dummy } template void FormatPermutationDomain(const TShaderPermutationDomain& InShaderPermutationDomain, FString& OutString, bool bFullNames, const TCHAR* Prefix) { const int32 Value = TDimension::ToDimensionValueId(InShaderPermutationDomain.template Get()); if (bFullNames) { if (!OutString.IsEmpty()) { OutString.AppendChar(TEXT('\n')); } if (Prefix != nullptr) { OutString.Append(Prefix); } if (TDimension::IsMultiDimensional) { OutString.Appendf(TEXT("TShaderPermutationDomain[%d]"), TDimension::PermutationCount); } if (Prefix != nullptr) { const FString ExtendedPrefix = FString::Printf(TEXT("%s -> "), Prefix); FormatPermutationParameter(InShaderPermutationDomain.template Get(), OutString, bFullNames, *ExtendedPrefix); } else { FormatPermutationParameter(InShaderPermutationDomain.template Get(), OutString, bFullNames, TEXT(" -> ")); } } else { if (!OutString.IsEmpty()) { OutString.AppendChar(TEXT(',')); } FormatPermutationParameter(InShaderPermutationDomain.template Get(), OutString, bFullNames, TEXT(" -> ")); } FormatPermutationDomain(InShaderPermutationDomain.GetTail(), OutString, bFullNames, Prefix); } template void FormatPermutationParameter(const typename TDimension::Type& E, FString& OutString, bool bFullNames, const TCHAR* Prefix) { if constexpr (TDimension::IsMultiDimensional) { FormatPermutationDomain(E, OutString, bFullNames, Prefix); } else if constexpr (std::is_base_of_v) { if (bFullNames) { OutString.Appendf(TEXT("%s (%s)"), TDimension::DefineName, !FShaderPermutationBool::ToDefineValue(E) ? TEXT("false") : TEXT("true")); } else { OutString.Appendf(TEXT("%d"), static_cast(FShaderPermutationBool::ToDefineValue(E))); } } else { if (bFullNames) { OutString.Appendf(TEXT("%s (%d)"), TDimension::DefineName, static_cast(TDimension::ToDefineValue(E))); } else { OutString.Appendf(TEXT("%d"), static_cast(TDimension::ToDefineValue(E))); } } } template bool DoesDimensionContainValue(const typename DimensionType::Type& Value) { for (int32 PermutationId = 0; PermutationId < DimensionType::PermutationCount; ++PermutationId) { if (Value == DimensionType::FromDimensionValueId(PermutationId)) { return true; } } return false; } }