// Copyright Epic Games, Inc. All Rights Reserved. #include "LuminTargetPlatform.h" #include "CoreTypes.h" #include "Misc/AssertionMacros.h" #include "Containers/Array.h" #include "Containers/UnrealString.h" #include "UObject/NameTypes.h" #include "Logging/LogMacros.h" #include "Stats/Stats.h" #if WITH_EDITOR #include "Materials/Material.h" #endif #include "LuminTargetDevice.h" #include "Modules/ModuleManager.h" /*============================================================================= LuminTargetPlatform.cpp: Implements the FLuminTargetPlatform class. =============================================================================*/ #define LOCTEXT_NAMESPACE "FLuminTargetPlatformModule" /* FLuminTargetPlatform structors *****************************************************************************/ FLuminTargetPlatform::FLuminTargetPlatform(bool bIsClient) // override the IniPlatformName up on the FTargetPlatformInfo : FAndroidTargetPlatform(bIsClient, nullptr, TEXT("Lumin")) { #if WITH_ENGINE RefreshSettings(); #endif } FLuminTargetPlatform::~FLuminTargetPlatform() { } bool FLuminTargetPlatform::IsSdkInstalled(bool bProjectHasCode, FString& OutDocumentationPath) const { // @todo Lumin: implement me OutDocumentationPath = FString("Shared/Tutorials/SettingUpLuminTutorial"); return true; } int32 FLuminTargetPlatform::CheckRequirements(bool bProjectHasCode, EBuildConfiguration Configuration, bool bRequiresAssetNativization, FString& OutTutorialPath, FString& OutDocumentationPath, FText& CustomizedLogMessage) const { OutDocumentationPath = TEXT("Platforms/Android/GettingStarted"); int32 bReadyToBuild = ETargetPlatformReadyStatus::Ready; if (!IsSdkInstalled(bProjectHasCode, OutTutorialPath)) { bReadyToBuild |= ETargetPlatformReadyStatus::SDKNotFound; } return bReadyToBuild; } bool FLuminTargetPlatform::SupportsMobileRendering() const { bool bUseMobileRendering = true; GetConfigSystem()->GetBool(TEXT("/Script/LuminRuntimeSettings.LuminRuntimeSettings"), TEXT("bUseMobileRendering"), bUseMobileRendering, GEngineIni); return bUseMobileRendering; } bool FLuminTargetPlatform::SupportsDesktopRendering() const { bool bUseMobileRendering = true; GetConfigSystem()->GetBool(TEXT("/Script/LuminRuntimeSettings.LuminRuntimeSettings"), TEXT("bUseMobileRendering"), bUseMobileRendering, GEngineIni); return bUseMobileRendering == false; } static bool LuminSupportsVulkan(FConfigCacheIni* ConfigSystem) { bool bSupportsVulkan = false; ConfigSystem->GetBool(TEXT("/Script/LuminRuntimeSettings.LuminRuntimeSettings"), TEXT("bUseVulkan"), bSupportsVulkan, GEngineIni); return bSupportsVulkan; } void FLuminTargetPlatform::RefreshSettings() { #if WITH_ENGINE //UE_LOG(LogCore, Warning, TEXT("*** DIAGNOSE - REFRESH!!!")); // Get the Target RHIs for this platform, we do not always want all those that are supported. TArray TargetedShaderFormats; GetAllTargetedShaderFormats(TargetedShaderFormats); // If we are targeting ES 2.0/3.1, we also must cook encoded HDR reflection captures static FName NAME_VULKAN_ES31(TEXT("SF_VULKAN_ES31_LUMIN")); static FName NAME_GLSL_ES3_1_ANDROID(TEXT("GLSL_ES3_1_ANDROID")); bRequiresEncodedHDRReflectionCaptures = TargetedShaderFormats.Contains(NAME_VULKAN_ES31) || TargetedShaderFormats.Contains(NAME_GLSL_ES3_1_ANDROID); #if WITH_EDITOR //ensure that we wipe out the material cached data before we begin serializing. It is cleared *after* a serialize, but changes made ini files will not be taken into account for materials without this TArray Materials; GetObjectsOfClass(UMaterial::StaticClass(), Materials, true); for (UObject* Material : Materials) { if (Material->GetOutermost() != GetTransientPackage()) { Material->ClearCachedCookedPlatformData(this); } } #endif #endif } bool FLuminTargetPlatform::SupportsFeature(ETargetPlatformFeatures Feature) const { switch (Feature) { case ETargetPlatformFeatures::Packaging: return true; case ETargetPlatformFeatures::LowQualityLightmaps: case ETargetPlatformFeatures::MobileRendering: return SupportsMobileRendering() || SupportsVulkan(); case ETargetPlatformFeatures::HighQualityLightmaps: //#todo-rco: Enable when Vulkan supports it //case ETargetPlatformFeatures::Tessellation: case ETargetPlatformFeatures::DeferredRendering: return SupportsDesktopRendering(); case ETargetPlatformFeatures::SoftwareOcclusion: return SupportsSoftwareOcclusion(); default: break; } return TTargetPlatformBase::SupportsFeature(Feature); } FAndroidTargetDevicePtr FLuminTargetPlatform::CreateTargetDevice(const ITargetPlatform& InTargetPlatform, const FString& InSerialNumber, const FString& InAndroidVariant) const { return MakeShareable(new FLuminTargetDevice(InTargetPlatform, InSerialNumber, InAndroidVariant)); } void FLuminTargetPlatform::InitializeDeviceDetection() { DeviceDetection = FModuleManager::LoadModuleChecked("AndroidDeviceDetection").GetAndroidDeviceDetection(TEXT("Lumin")); DeviceDetection->Initialize(TEXT("MLSDK"), #if PLATFORM_WINDOWS TEXT("tools/mldb/mldb.exe"), #else TEXT("tools/mldb/mldb"), #endif TEXT("getprop"), /*bGetExtensionsViaSurfaceFlinger*/ false, /*bForLumin*/ true); } #if WITH_ENGINE void FLuminTargetPlatform::GetAllPossibleShaderFormats( TArray& OutFormats ) const { // @todo Lumin: re-use Android version? Make sure Android has VULKAN_SM5 static FName NAME_GLSL_ES3_1_ANDROID(TEXT("GLSL_ES3_1_ANDROID")); static FName NAME_VULKAN_SM5_LUMIN(TEXT("SF_VULKAN_SM5_LUMIN")); static FName NAME_VULKAN_ES31_LUMIN(TEXT("SF_VULKAN_ES31_LUMIN")); if (SupportsMobileRendering()) { if (LuminSupportsVulkan(GetConfigSystem())) { OutFormats.AddUnique(NAME_VULKAN_ES31_LUMIN); } else { OutFormats.AddUnique(NAME_GLSL_ES3_1_ANDROID); } } if (SupportsDesktopRendering()) { if (LuminSupportsVulkan(GetConfigSystem())) { OutFormats.AddUnique(NAME_VULKAN_SM5_LUMIN); } } } static FName FormatRemap[][2] = { // Default format: ASTC format: { { FName(TEXT("DXT1")) },{ FName(TEXT("ASTC_RGB")) } }, { { FName(TEXT("DXT5")) },{ FName(TEXT("ASTC_RGBA")) } }, { { FName(TEXT("DXT5n")) },{ FName(TEXT("ASTC_NormalAG")) } }, { { FName(TEXT("BC5")) },{ FName(TEXT("ASTC_NormalRG")) } }, { { FName(TEXT("BC6H")) },{ FName(TEXT("ASTC_RGB")) } }, { { FName(TEXT("BC7")) },{ FName(TEXT("ASTC_RGBAuto")) } }, { { FName(TEXT("AutoDXT")) },{ FName(TEXT("ASTC_RGBAuto")) } }, }; void FLuminTargetPlatform::GetTextureFormats(const UTexture* InTexture, TArray< TArray >& OutFormats) const { check(InTexture); GetDefaultTextureFormatNamePerLayer(OutFormats.AddDefaulted_GetRef(), this, InTexture, false); for (FName& TextureFormatName : OutFormats.Last()) { // forward rendering only needs one channel for shadow maps if (InTexture->LODGroup == TEXTUREGROUP_Shadowmap) { TextureFormatName = FName(TEXT("G8")); } else { for (int32 RemapIndex = 0; RemapIndex < UE_ARRAY_COUNT(FormatRemap); ++RemapIndex) { if (TextureFormatName == FormatRemap[RemapIndex][0]) { // we found a remapping TextureFormatName = FormatRemap[RemapIndex][1]; break; } } } } } void FLuminTargetPlatform::GetAllTextureFormats(TArray& OutFormats) const { GetAllDefaultTextureFormats(this, OutFormats, false); for (int32 RemapIndex = 0; RemapIndex < UE_ARRAY_COUNT(FormatRemap); RemapIndex++) { OutFormats.Remove(FormatRemap[RemapIndex][0]); } // include the formats we want for (int32 RemapIndex = 0; RemapIndex < UE_ARRAY_COUNT(FormatRemap); RemapIndex++) { OutFormats.AddUnique(FormatRemap[RemapIndex][1]); } } #endif //WITH_ENGINE #undef LOCTEXT_NAMESPACE