You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
530 lines
15 KiB
C++
530 lines
15 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Common/TargetPlatformBase.h"
|
|
#include "Misc/ConfigCacheIni.h"
|
|
#include "LocalPcTargetDevice.h"
|
|
|
|
#if WITH_ENGINE
|
|
#include "Sound/SoundWave.h"
|
|
#include "TextureResource.h"
|
|
#include "Engine/VolumeTexture.h"
|
|
#include "StaticMeshResources.h"
|
|
#include "RHI.h"
|
|
#endif // WITH_ENGINE
|
|
|
|
#define LOCTEXT_NAMESPACE "TGenericWindowsTargetPlatform"
|
|
|
|
/**
|
|
* Template for Windows target platforms
|
|
*/
|
|
template<bool HAS_EDITOR_DATA, bool IS_DEDICATED_SERVER, bool IS_CLIENT_ONLY>
|
|
class TGenericWindowsTargetPlatform
|
|
: public TTargetPlatformBase<FWindowsPlatformProperties<HAS_EDITOR_DATA, IS_DEDICATED_SERVER, IS_CLIENT_ONLY> >
|
|
{
|
|
public:
|
|
typedef FWindowsPlatformProperties<HAS_EDITOR_DATA, IS_DEDICATED_SERVER, IS_CLIENT_ONLY> TProperties;
|
|
typedef TTargetPlatformBase<TProperties> TSuper;
|
|
|
|
/**
|
|
* Default constructor.
|
|
*/
|
|
TGenericWindowsTargetPlatform( )
|
|
{
|
|
#if PLATFORM_WINDOWS
|
|
// only add local device if actually running on Windows
|
|
LocalDevice = MakeShareable(new TLocalPcTargetDevice<PLATFORM_64BITS>(*this));
|
|
#endif
|
|
|
|
#if WITH_ENGINE
|
|
FConfigCacheIni::LoadLocalIniFile(EngineSettings, TEXT("Engine"), true, *this->PlatformName());
|
|
TextureLODSettings = nullptr; // These are registered by the device profile system.
|
|
StaticMeshLODSettings.Initialize(EngineSettings);
|
|
|
|
|
|
// Get the Target RHIs for this platform, we do not always want all those that are supported.
|
|
TArray<FName> TargetedShaderFormats;
|
|
GetAllTargetedShaderFormats(TargetedShaderFormats);
|
|
|
|
static FName NAME_PCD3D_SM5(TEXT("PCD3D_SM5"));
|
|
static FName NAME_PCD3D_SM4(TEXT("PCD3D_SM4"));
|
|
static FName NAME_VULKAN_SM5(TEXT("SF_VULKAN_SM5"));
|
|
|
|
bSupportDX11TextureFormats = true;
|
|
bSupportCompressedVolumeTexture = true;
|
|
|
|
for (FName TargetedShaderFormat : TargetedShaderFormats)
|
|
{
|
|
EShaderPlatform ShaderPlatform = SP_NumPlatforms;
|
|
// Can't use ShaderFormatToLegacyShaderPlatform() because of link dependency
|
|
{
|
|
if (TargetedShaderFormat == NAME_PCD3D_SM5)
|
|
{
|
|
ShaderPlatform = SP_PCD3D_SM5;
|
|
}
|
|
else if (TargetedShaderFormat == NAME_PCD3D_SM4)
|
|
{
|
|
ShaderPlatform = SP_PCD3D_SM4;
|
|
}
|
|
else if (TargetedShaderFormat == NAME_VULKAN_SM5)
|
|
{
|
|
ShaderPlatform = SP_VULKAN_SM5;
|
|
}
|
|
}
|
|
|
|
// If we're targeting only DX11 we can use DX11 texture formats. Otherwise we'd have to compress fallbacks and increase the size of cooked content significantly.
|
|
if (ShaderPlatform != SP_PCD3D_SM5 && ShaderPlatform != SP_VULKAN_SM5)
|
|
{
|
|
bSupportDX11TextureFormats = false;
|
|
}
|
|
if (!UVolumeTexture::ShaderPlatformSupportsCompression(ShaderPlatform))
|
|
{
|
|
bSupportCompressedVolumeTexture = false;
|
|
}
|
|
}
|
|
|
|
// If we are targeting ES 2.0/3.1, we also must cook encoded HDR reflection captures
|
|
static FName NAME_SF_VULKAN_ES31(TEXT("SF_VULKAN_ES31"));
|
|
static FName NAME_OPENGL_150_ES2(TEXT("GLSL_150_ES2"));
|
|
static FName NAME_OPENGL_150_ES3_1(TEXT("GLSL_150_ES31"));
|
|
bRequiresEncodedHDRReflectionCaptures = TargetedShaderFormats.Contains(NAME_SF_VULKAN_ES31)
|
|
|| TargetedShaderFormats.Contains(NAME_OPENGL_150_ES2)
|
|
|| TargetedShaderFormats.Contains(NAME_OPENGL_150_ES3_1);
|
|
#endif
|
|
}
|
|
|
|
public:
|
|
|
|
//~ Begin ITargetPlatform Interface
|
|
|
|
virtual void EnableDeviceCheck(bool OnOff) override {}
|
|
|
|
virtual void GetAllDevices( TArray<ITargetDevicePtr>& OutDevices ) const override
|
|
{
|
|
OutDevices.Reset();
|
|
if (LocalDevice.IsValid())
|
|
{
|
|
OutDevices.Add(LocalDevice);
|
|
}
|
|
}
|
|
|
|
virtual bool GenerateStreamingInstallManifest(const TMultiMap<FString, int32>& PakchunkMap, const TSet<int32>& PakchunkIndicesInUse) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual ITargetDevicePtr GetDefaultDevice( ) const override
|
|
{
|
|
if (LocalDevice.IsValid())
|
|
{
|
|
return LocalDevice;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
virtual ITargetDevicePtr GetDevice( const FTargetDeviceId& DeviceId )
|
|
{
|
|
if (LocalDevice.IsValid() && (DeviceId == LocalDevice->GetId()))
|
|
{
|
|
return LocalDevice;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
virtual bool IsRunningPlatform( ) const override
|
|
{
|
|
// Must be Windows platform as editor for this to be considered a running platform
|
|
return PLATFORM_WINDOWS && !UE_SERVER && !UE_GAME && WITH_EDITOR && HAS_EDITOR_DATA;
|
|
}
|
|
|
|
virtual bool SupportsFeature( ETargetPlatformFeatures Feature ) const override
|
|
{
|
|
// we currently do not have a build target for WindowsServer
|
|
if (Feature == ETargetPlatformFeatures::Packaging)
|
|
{
|
|
return (HAS_EDITOR_DATA || !IS_DEDICATED_SERVER);
|
|
}
|
|
|
|
if ( Feature == ETargetPlatformFeatures::ShouldSplitPaksIntoSmallerSizes )
|
|
{
|
|
return IS_CLIENT_ONLY;
|
|
}
|
|
|
|
if (Feature == ETargetPlatformFeatures::MobileRendering)
|
|
{
|
|
static bool bCachedSupportsMobileRendering = false;
|
|
#if WITH_ENGINE
|
|
static bool bHasCachedValue = false;
|
|
if (!bHasCachedValue)
|
|
{
|
|
TArray<FName> TargetedShaderFormats;
|
|
GetAllTargetedShaderFormats(TargetedShaderFormats);
|
|
|
|
for (const FName& Format : TargetedShaderFormats)
|
|
{
|
|
if (IsMobilePlatform(ShaderFormatToLegacyShaderPlatform(Format)))
|
|
{
|
|
bCachedSupportsMobileRendering = true;
|
|
break;
|
|
}
|
|
}
|
|
bHasCachedValue = true;
|
|
}
|
|
#endif
|
|
|
|
return bCachedSupportsMobileRendering;
|
|
}
|
|
|
|
return TSuper::SupportsFeature(Feature);
|
|
}
|
|
|
|
virtual void GetBuildProjectSettingKeys(FString& OutSection, TArray<FString>& InBoolKeys, TArray<FString>& InIntKeys, TArray<FString>& InStringKeys) const override
|
|
{
|
|
OutSection = TEXT("/Script/WindowsTargetPlatform.WindowsTargetSettings");
|
|
InStringKeys.Add(TEXT("MinimumOSVersion"));
|
|
}
|
|
|
|
#if WITH_ENGINE
|
|
virtual void GetReflectionCaptureFormats(TArray<FName>& OutFormats) const override
|
|
{
|
|
if (bRequiresEncodedHDRReflectionCaptures)
|
|
{
|
|
OutFormats.Add(FName(TEXT("EncodedHDR")));
|
|
}
|
|
|
|
OutFormats.Add(FName(TEXT("FullHDR")));
|
|
}
|
|
|
|
virtual void GetAllPossibleShaderFormats( TArray<FName>& OutFormats ) const override
|
|
{
|
|
// no shaders needed for dedicated server target
|
|
if (!IS_DEDICATED_SERVER)
|
|
{
|
|
static FName NAME_PCD3D_SM5(TEXT("PCD3D_SM5"));
|
|
static FName NAME_PCD3D_SM4(TEXT("PCD3D_SM4"));
|
|
static FName NAME_GLSL_150(TEXT("GLSL_150"));
|
|
static FName NAME_GLSL_430(TEXT("GLSL_430"));
|
|
static FName NAME_VULKAN_ES31(TEXT("SF_VULKAN_ES31"));
|
|
static FName NAME_OPENGL_150_ES2(TEXT("GLSL_150_ES2"));
|
|
static FName NAME_OPENGL_150_ES3_1(TEXT("GLSL_150_ES31"));
|
|
static FName NAME_VULKAN_SM5(TEXT("SF_VULKAN_SM5"));
|
|
static FName NAME_PCD3D_ES3_1(TEXT("PCD3D_ES31"));
|
|
static FName NAME_PCD3D_ES2(TEXT("PCD3D_ES2"));
|
|
|
|
OutFormats.AddUnique(NAME_PCD3D_SM5);
|
|
OutFormats.AddUnique(NAME_PCD3D_SM4);
|
|
OutFormats.AddUnique(NAME_GLSL_150);
|
|
OutFormats.AddUnique(NAME_GLSL_430);
|
|
OutFormats.AddUnique(NAME_VULKAN_ES31);
|
|
OutFormats.AddUnique(NAME_OPENGL_150_ES2);
|
|
OutFormats.AddUnique(NAME_OPENGL_150_ES3_1);
|
|
OutFormats.AddUnique(NAME_VULKAN_SM5);
|
|
OutFormats.AddUnique(NAME_PCD3D_ES3_1);
|
|
OutFormats.AddUnique(NAME_PCD3D_ES2);
|
|
}
|
|
}
|
|
|
|
virtual void GetAllTargetedShaderFormats( TArray<FName>& OutFormats ) const override
|
|
{
|
|
// Get the Target RHIs for this platform, we do not always want all those that are supported. (reload in case user changed in the editor)
|
|
TArray<FString>TargetedShaderFormats;
|
|
GConfig->GetArray(TEXT("/Script/WindowsTargetPlatform.WindowsTargetSettings"), TEXT("TargetedRHIs"), TargetedShaderFormats, GEngineIni);
|
|
|
|
// Gather the list of Target RHIs and filter out any that may be invalid.
|
|
TArray<FName> PossibleShaderFormats;
|
|
GetAllPossibleShaderFormats(PossibleShaderFormats);
|
|
|
|
for (int32 ShaderFormatIdx = TargetedShaderFormats.Num() - 1; ShaderFormatIdx >= 0; ShaderFormatIdx--)
|
|
{
|
|
FString ShaderFormat = TargetedShaderFormats[ShaderFormatIdx];
|
|
if (PossibleShaderFormats.Contains(FName(*ShaderFormat)) == false)
|
|
{
|
|
TargetedShaderFormats.RemoveAt(ShaderFormatIdx);
|
|
}
|
|
}
|
|
|
|
for(const FString& ShaderFormat : TargetedShaderFormats)
|
|
{
|
|
OutFormats.AddUnique(FName(*ShaderFormat));
|
|
}
|
|
}
|
|
virtual const class FStaticMeshLODSettings& GetStaticMeshLODSettings( ) const override
|
|
{
|
|
return StaticMeshLODSettings;
|
|
}
|
|
|
|
virtual void GetTextureFormats( const UTexture* InTexture, TArray< TArray<FName> >& OutFormats) const override
|
|
{
|
|
if (!IS_DEDICATED_SERVER)
|
|
{
|
|
GetDefaultTextureFormatNamePerLayer(OutFormats.AddDefaulted_GetRef(), this, InTexture, EngineSettings, bSupportDX11TextureFormats, bSupportCompressedVolumeTexture);
|
|
}
|
|
}
|
|
|
|
virtual void GetAllTextureFormats(TArray<FName>& OutFormats) const override
|
|
{
|
|
if (!IS_DEDICATED_SERVER)
|
|
{
|
|
GetAllDefaultTextureFormats(this, OutFormats, bSupportDX11TextureFormats);
|
|
}
|
|
}
|
|
|
|
FName GetVirtualTextureLayerFormat(int32 SourceFormat, bool bAllowCompression, bool bNoAlpha, bool bDX11TextureFormatsSupported, int32 Settings) const override
|
|
{
|
|
FName TextureFormatName = NAME_None;
|
|
|
|
// Supported texture format names.
|
|
static FName NameDXT1(TEXT("DXT1"));
|
|
static FName NameDXT3(TEXT("DXT3"));
|
|
static FName NameDXT5(TEXT("DXT5"));
|
|
static FName NameDXT5n(TEXT("DXT5n"));
|
|
static FName NameBC4(TEXT("BC4"));
|
|
static FName NameBC5(TEXT("BC5"));
|
|
static FName NameBGRA8(TEXT("BGRA8"));
|
|
static FName NameXGXR8(TEXT("XGXR8"));
|
|
static FName NameG8(TEXT("G8"));
|
|
static FName NameVU8(TEXT("VU8"));
|
|
static FName NameRGBA16F(TEXT("RGBA16F"));
|
|
static FName NameBC6H(TEXT("BC6H"));
|
|
static FName NameBC7(TEXT("BC7"));
|
|
|
|
// Note: We can't use things here like autoDXT here which defer the exact choice to the compressor as it would mean that
|
|
// some textures on a VT layer may get a different format than others.
|
|
// We need to guarantee the format to be the same for all textures on the layer so we need to decide on the exact final format here.
|
|
|
|
bool bUseDXT5NormalMap = false;
|
|
FString UseDXT5NormalMapsString;
|
|
if (EngineSettings.GetString(TEXT("SystemSettings"), TEXT("Compat.UseDXT5NormalMaps"), UseDXT5NormalMapsString))
|
|
{
|
|
bUseDXT5NormalMap = FCString::ToBool(*UseDXT5NormalMapsString);
|
|
}
|
|
|
|
// Determine the pixel format of the (un/)compressed texture
|
|
if (!bAllowCompression)
|
|
{
|
|
if (SourceFormat == TSF_RGBA16F)
|
|
{
|
|
TextureFormatName = NameRGBA16F;
|
|
}
|
|
else if (SourceFormat == TSF_G8 || Settings == TC_Grayscale)
|
|
{
|
|
TextureFormatName = NameG8;
|
|
}
|
|
else if (Settings == TC_Normalmap && bUseDXT5NormalMap)
|
|
{
|
|
TextureFormatName = NameXGXR8;
|
|
}
|
|
else
|
|
{
|
|
TextureFormatName = NameBGRA8;
|
|
}
|
|
}
|
|
else if (Settings == TC_HDR)
|
|
{
|
|
TextureFormatName = NameRGBA16F;
|
|
}
|
|
else if (Settings == TC_Normalmap)
|
|
{
|
|
TextureFormatName = bUseDXT5NormalMap ? NameDXT5n : NameBC5;
|
|
}
|
|
else if (Settings == TC_Displacementmap)
|
|
{
|
|
TextureFormatName = NameG8;
|
|
}
|
|
else if (Settings == TC_VectorDisplacementmap)
|
|
{
|
|
TextureFormatName = NameBGRA8;
|
|
}
|
|
else if (Settings == TC_Grayscale)
|
|
{
|
|
TextureFormatName = NameG8;
|
|
}
|
|
else if (Settings == TC_Alpha)
|
|
{
|
|
TextureFormatName = NameBC4;
|
|
}
|
|
else if (Settings == TC_DistanceFieldFont)
|
|
{
|
|
TextureFormatName = NameG8;
|
|
}
|
|
else if (Settings == TC_HDR_Compressed)
|
|
{
|
|
TextureFormatName = NameBC6H;
|
|
}
|
|
else if (Settings == TC_BC7)
|
|
{
|
|
TextureFormatName = NameBC7;
|
|
}
|
|
else if (bNoAlpha)
|
|
{
|
|
TextureFormatName = NameDXT1;
|
|
}
|
|
else
|
|
{
|
|
TextureFormatName = NameDXT5;
|
|
}
|
|
|
|
/*
|
|
FIXME: IS this still relevant for VT ? comes from the texture variant
|
|
// Some PC GPUs don't support sRGB read from G8 textures (e.g. AMD DX10 cards on ShaderModel3.0)
|
|
// This solution requires 4x more memory but a lot of PC HW emulate the format anyway
|
|
if ((TextureFormatName == NameG8) && Texture->SRGB && !SupportsFeature(ETargetPlatformFeatures::GrayscaleSRGB))
|
|
{
|
|
TextureFormatName = NameBGRA8;
|
|
}*/
|
|
|
|
// fallback to non-DX11 formats if one was chosen, but we can't use it
|
|
if (!bDX11TextureFormatsSupported)
|
|
{
|
|
if (TextureFormatName == NameBC6H)
|
|
{
|
|
TextureFormatName = NameRGBA16F;
|
|
}
|
|
else if (TextureFormatName == NameBC7)
|
|
{
|
|
TextureFormatName = NameDXT5;
|
|
}
|
|
}
|
|
|
|
return TextureFormatName;
|
|
}
|
|
|
|
virtual const UTextureLODSettings& GetTextureLODSettings() const override
|
|
{
|
|
return *TextureLODSettings;
|
|
}
|
|
|
|
virtual void RegisterTextureLODSettings(const UTextureLODSettings* InTextureLODSettings) override
|
|
{
|
|
TextureLODSettings = InTextureLODSettings;
|
|
}
|
|
|
|
virtual FName GetWaveFormat( const class USoundWave* Wave ) const override
|
|
{
|
|
static const FName NAME_ADPCM(TEXT("ADPCM"));
|
|
static const FName NAME_OGG(TEXT("OGG"));
|
|
static const FName NAME_OPUS(TEXT("OPUS"));
|
|
|
|
// Seekable streams need to pick a codec which allows fixed-sized frames so we can compute stream chunk index to load
|
|
if (Wave->IsSeekableStreaming())
|
|
{
|
|
return NAME_ADPCM;
|
|
}
|
|
|
|
#if !USE_VORBIS_FOR_STREAMING
|
|
if (Wave->IsStreaming())
|
|
{
|
|
return NAME_OPUS;
|
|
}
|
|
#endif
|
|
|
|
return NAME_OGG;
|
|
}
|
|
|
|
virtual void GetAllWaveFormats(TArray<FName>& OutFormats) const override
|
|
{
|
|
static const FName NAME_ADPCM(TEXT("ADPCM"));
|
|
static FName NAME_OGG(TEXT("OGG"));
|
|
static FName NAME_OPUS(TEXT("OPUS"));
|
|
|
|
OutFormats.Add(NAME_ADPCM);
|
|
OutFormats.Add(NAME_OGG);
|
|
OutFormats.Add(NAME_OPUS);
|
|
}
|
|
|
|
virtual FPlatformAudioCookOverrides* GetAudioCompressionSettings() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
#endif //WITH_ENGINE
|
|
|
|
virtual bool SupportsVariants() const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual FText GetVariantDisplayName() const override
|
|
{
|
|
if (IS_DEDICATED_SERVER)
|
|
{
|
|
return LOCTEXT("WindowsServerVariantTitle", "Dedicated Server");
|
|
}
|
|
|
|
if (HAS_EDITOR_DATA)
|
|
{
|
|
return LOCTEXT("WindowsClientEditorDataVariantTitle", "Client with Editor Data");
|
|
}
|
|
|
|
if (IS_CLIENT_ONLY)
|
|
{
|
|
return LOCTEXT("WindowsClientOnlyVariantTitle", "Client only");
|
|
}
|
|
|
|
return LOCTEXT("WindowsClientVariantTitle", "Client");
|
|
}
|
|
|
|
virtual FText GetVariantTitle() const override
|
|
{
|
|
return LOCTEXT("WindowsVariantTitle", "Build Type");
|
|
}
|
|
|
|
virtual float GetVariantPriority() const override
|
|
{
|
|
return TProperties::GetVariantPriority();
|
|
}
|
|
|
|
DECLARE_DERIVED_EVENT(TGenericWindowsTargetPlatform, ITargetPlatform::FOnTargetDeviceDiscovered, FOnTargetDeviceDiscovered);
|
|
virtual FOnTargetDeviceDiscovered& OnDeviceDiscovered( ) override
|
|
{
|
|
return DeviceDiscoveredEvent;
|
|
}
|
|
|
|
DECLARE_DERIVED_EVENT(TGenericWindowsTargetPlatform, ITargetPlatform::FOnTargetDeviceLost, FOnTargetDeviceLost);
|
|
virtual FOnTargetDeviceLost& OnDeviceLost( ) override
|
|
{
|
|
return DeviceLostEvent;
|
|
}
|
|
|
|
//~ End ITargetPlatform Interface
|
|
|
|
private:
|
|
|
|
// Holds the local device.
|
|
ITargetDevicePtr LocalDevice;
|
|
|
|
#if WITH_ENGINE
|
|
// Holds the Engine INI settings for quick use.
|
|
FConfigFile EngineSettings;
|
|
|
|
// Holds the texture LOD settings.
|
|
const UTextureLODSettings* TextureLODSettings;
|
|
|
|
// Holds static mesh LOD settings.
|
|
FStaticMeshLODSettings StaticMeshLODSettings;
|
|
|
|
// True if the project supports non-DX11 texture formats.
|
|
bool bSupportDX11TextureFormats;
|
|
|
|
// True if the project requires encoded HDR reflection captures
|
|
bool bRequiresEncodedHDRReflectionCaptures;
|
|
|
|
// True if the project supports only compressed volume texture formats.
|
|
bool bSupportCompressedVolumeTexture;
|
|
#endif // WITH_ENGINE
|
|
|
|
private:
|
|
|
|
// Holds an event delegate that is executed when a new target device has been discovered.
|
|
FOnTargetDeviceDiscovered DeviceDiscoveredEvent;
|
|
|
|
// Holds an event delegate that is executed when a target device has been lost, i.e. disconnected or timed out.
|
|
FOnTargetDeviceLost DeviceLostEvent;
|
|
};
|
|
|
|
#undef LOCTEXT_NAMESPACE
|