UDeviceProfileManager::LoadProfiles() not loading profiles for running platform in Test builds

Hello there,

In Test builds in 5.6, it looks like device profiles for the current platform are not loaded in `UDeviceProfileManager::LoadProfiles()`, so subsequent calls to `UDeviceProfileManager::FindProfile` do not work as expected.

In `UDeviceProfileManager::LoadProfiles()` there is the following snippet

`void UDeviceProfileManager::LoadProfiles()
{
if( !HasAnyFlags( RF_ClassDefaultObject ) )
{
UE::ConfigAccessTracking::FIgnoreScope IgnoreConfigAccessTracking = UE::ConfigAccessTracking::FIgnoreScope();

TMap<FString, FString> DeviceProfileToPlatformConfigMap;
DeviceProfileToPlatformConfigMap.Add(TEXT(“GlobalDefaults,None”), FPlatformProperties::IniPlatformName());

#if ALLOW_OTHER_PLATFORM_CONFIG
TArray PlatformsToLoad = FDataDrivenPlatformInfoRegistry::GetSortedPlatformNames(EPlatformInfoType::TruePlatformsOnly);

// go over all the platforms we find, starting with the current platform
for (int32 PlatformIndex = 0; PlatformIndex <= PlatformsToLoad.Num(); PlatformIndex++)
{
// which platform’s set of ini files should we load from?
FString ConfigLoadPlatform = PlatformIndex == 0 ? FString(FPlatformProperties::IniPlatformName()) : PlatformsToLoad[PlatformIndex - 1].ToString();

// load the DP.ini files (from current platform and then by the extra confidential platforms)
FConfigFile LocalPlatformConfigFile;
const FConfigFile* PlatformConfigFile = FConfigCacheIni::FindOrLoadPlatformConfig(LocalPlatformConfigFile, TEXT(“DeviceProfiles”), *ConfigLoadPlatform);

// load all of the DeviceProfiles
TArray ProfileDescriptions;
PlatformConfigFile->GetArray(TEXT(“DeviceProfiles”), TEXT(“DeviceProfileNameAndTypes”), ProfileDescriptions);

// add them to our collection of profiles by platform
for (const FString& Desc : ProfileDescriptions)
{
if (!DeviceProfileToPlatformConfigMap.Contains(Desc))
{
DeviceProfileToPlatformConfigMap.Add(Desc, ConfigLoadPlatform);
}
}
}
#endif
.
.
.`

Notice, since ALLOW_OTHER_PLATFORM_CONFIG is 0 in Test builds, the current platform, which should be handled by the 0th array iteration, is not considered when creating device profiles in Test.

Locally, we have found that this minor modification to always iterate over the current platform solves this issue.

`void UDeviceProfileManager::LoadProfiles()
{
if( !HasAnyFlags( RF_ClassDefaultObject ) )
{
UE::ConfigAccessTracking::FIgnoreScope IgnoreConfigAccessTracking = UE::ConfigAccessTracking::FIgnoreScope();

TMap<FString, FString> DeviceProfileToPlatformConfigMap;
DeviceProfileToPlatformConfigMap.Add(TEXT(“GlobalDefaults,None”), FPlatformProperties::IniPlatformName());

TArray PlatformsToLoad({FPlatformProperties::IniPlatformName()});
#if ALLOW_OTHER_PLATFORM_CONFIG
PlatformsToLoad = FDataDrivenPlatformInfoRegistry::GetSortedPlatformNames(EPlatformInfoType::TruePlatformsOnly);
#endif

// go over all the platforms we find, starting with the current platform
for (int32 PlatformIndex = 0; PlatformIndex < PlatformsToLoad.Num(); PlatformIndex++)
{
// which platform’s set of ini files should we load from?
FString ConfigLoadPlatform = PlatformsToLoad[PlatformIndex].ToString();
.
.
.`Is this an acceptable fix for this problem?

Our alternate solution is to specify that profiles should be created if not found as a parameter to our calls to `UDeviceProfileManager::FindProfile` but this feels like an error-prone workaround to the issue present in `UDeviceProfileManager::LoadProfiles()`

Thanks for your help!

Hi,

I think your fix is reasonable, but it will always load all the platform profiles which I think is not desirable in a Shipping build as it would waste memory, though one could argue that the the profiles are small… except the devs scratching for every bytes of memory of low end platforms… My interpretation is that in development, we don’t really mind loading tons of device profiles, but in Test/Shipping, the design will load on-demand only (pay for what you use). The function FindProfile() declaration parameter also defaults to create the profile if the profile is not found in memory. So it looks like that not loading the profiles is intended, especially on Android where they are many profiles and the expectation if to call FindProfile or CreateProfile manually.

ENGINE_API UDeviceProfile* FindProfile(const FString& ProfileName, bool bCreateProfileOnFail = true, FName OptionalPlatformName = FName());Otherwise, like I said, your change looks reasonable, probably fine, but there might be some edge cases I haven’t considered.

Regards,

Patrick

Hi,

No, I’m not aware of plans to get the device profile API better. It might get some work if it gets in the way of some of the internal initiatives, but it is unlikely going to move in short/mid term.

Regards,

Patrick

Thanks for your prompt reply Patrick! Given your rationale for why LoadProfiles() is this way, I think we’ll go ahead with creating profiles if not found via FindProfile() to avoid diverging our engine with respect to UE main.

Are there any plans to make this device profile API more robust and less error prone? Namely in the case someone passes a bad profile name string to FindProfile()?

Thanks again!