Add ASTC texture compression on Android
This commit is contained in:
@@ -22,6 +22,11 @@ IMPLEMENT_ENGINE_SETTINGS_GETTER(AndroidPlatformSettings, AndroidPlatform);
|
||||
|
||||
namespace
|
||||
{
|
||||
struct AndroidPlatformCache
|
||||
{
|
||||
AndroidPlatformSettings::TextureQuality TexturesQuality;
|
||||
};
|
||||
|
||||
void DeployIcon(const CookingData& data, const TextureData& iconData, const Char* subDir, int32 iconSize, int32 adaptiveIconSize)
|
||||
{
|
||||
const String mipmapPath = data.OriginalOutputPath / TEXT("app/src/main/res") / subDir;
|
||||
@@ -30,6 +35,24 @@ namespace
|
||||
FileSystem::CreateDirectory(mipmapPath);
|
||||
EditorUtilities::ExportApplicationImage(iconData, iconSize, iconSize, PixelFormat::B8G8R8A8_UNorm, iconPath);
|
||||
}
|
||||
|
||||
PixelFormat GetQualityTextureFormat(bool sRGB, PixelFormat format)
|
||||
{
|
||||
const auto platformSettings = AndroidPlatformSettings::Get();
|
||||
switch (platformSettings->TexturesQuality)
|
||||
{
|
||||
case AndroidPlatformSettings::TextureQuality::Uncompressed:
|
||||
return PixelFormatExtensions::FindUncompressedFormat(format);
|
||||
case AndroidPlatformSettings::TextureQuality::ASTC_High:
|
||||
return sRGB ? PixelFormat::ASTC_4x4_UNorm_sRGB : PixelFormat::ASTC_4x4_UNorm;
|
||||
case AndroidPlatformSettings::TextureQuality::ASTC_Medium:
|
||||
return sRGB ? PixelFormat::ASTC_6x6_UNorm_sRGB : PixelFormat::ASTC_6x6_UNorm;
|
||||
case AndroidPlatformSettings::TextureQuality::ASTC_Low:
|
||||
return sRGB ? PixelFormat::ASTC_8x8_UNorm_sRGB : PixelFormat::ASTC_8x8_UNorm;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Char* AndroidPlatformTools::GetDisplayName() const
|
||||
@@ -54,62 +77,67 @@ ArchitectureType AndroidPlatformTools::GetArchitecture() const
|
||||
|
||||
PixelFormat AndroidPlatformTools::GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format)
|
||||
{
|
||||
// TODO: add ETC compression support for Android
|
||||
// TODO: add ASTC compression support for Android
|
||||
|
||||
// BC formats are not widely supported on Android
|
||||
if (PixelFormatExtensions::IsCompressedBC(format))
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PixelFormat::BC1_Typeless:
|
||||
case PixelFormat::BC2_Typeless:
|
||||
case PixelFormat::BC3_Typeless:
|
||||
return PixelFormat::R8G8B8A8_Typeless;
|
||||
case PixelFormat::BC1_UNorm:
|
||||
case PixelFormat::BC2_UNorm:
|
||||
case PixelFormat::BC3_UNorm:
|
||||
return PixelFormat::R8G8B8A8_UNorm;
|
||||
case PixelFormat::BC1_UNorm_sRGB:
|
||||
case PixelFormat::BC2_UNorm_sRGB:
|
||||
case PixelFormat::BC3_UNorm_sRGB:
|
||||
return PixelFormat::R8G8B8A8_UNorm_sRGB;
|
||||
case PixelFormat::BC4_Typeless:
|
||||
return PixelFormat::R8_Typeless;
|
||||
case PixelFormat::BC4_UNorm:
|
||||
return PixelFormat::R8_UNorm;
|
||||
case PixelFormat::BC4_SNorm:
|
||||
return PixelFormat::R8_SNorm;
|
||||
case PixelFormat::BC5_Typeless:
|
||||
return PixelFormat::R16G16_Typeless;
|
||||
case PixelFormat::BC5_UNorm:
|
||||
return PixelFormat::R16G16_UNorm;
|
||||
case PixelFormat::BC5_SNorm:
|
||||
return PixelFormat::R16G16_SNorm;
|
||||
case PixelFormat::BC7_Typeless:
|
||||
case PixelFormat::BC6H_Typeless:
|
||||
return PixelFormat::R16G16B16A16_Typeless;
|
||||
case PixelFormat::BC7_UNorm:
|
||||
case PixelFormat::BC6H_Uf16:
|
||||
case PixelFormat::BC6H_Sf16:
|
||||
return PixelFormat::R16G16B16A16_Float;
|
||||
case PixelFormat::BC7_UNorm_sRGB:
|
||||
return PixelFormat::R16G16B16A16_UNorm;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
// Not all Android devices support R11G11B10 textures (eg. M6 Note)
|
||||
case PixelFormat::R11G11B10_Float:
|
||||
// Not all Android devices support R11G11B10 textures (eg. M6 Note)
|
||||
return PixelFormat::R16G16B16A16_UNorm;
|
||||
case PixelFormat::BC1_Typeless:
|
||||
case PixelFormat::BC2_Typeless:
|
||||
case PixelFormat::BC3_Typeless:
|
||||
case PixelFormat::BC4_Typeless:
|
||||
case PixelFormat::BC5_Typeless:
|
||||
case PixelFormat::BC1_UNorm:
|
||||
case PixelFormat::BC2_UNorm:
|
||||
case PixelFormat::BC3_UNorm:
|
||||
case PixelFormat::BC4_UNorm:
|
||||
case PixelFormat::BC5_UNorm:
|
||||
return GetQualityTextureFormat(false, format);
|
||||
case PixelFormat::BC1_UNorm_sRGB:
|
||||
case PixelFormat::BC2_UNorm_sRGB:
|
||||
case PixelFormat::BC3_UNorm_sRGB:
|
||||
case PixelFormat::BC7_UNorm_sRGB:
|
||||
return GetQualityTextureFormat(true, format);
|
||||
case PixelFormat::BC4_SNorm:
|
||||
return PixelFormat::R8_SNorm;
|
||||
case PixelFormat::BC5_SNorm:
|
||||
return PixelFormat::R16G16_SNorm;
|
||||
case PixelFormat::BC6H_Typeless:
|
||||
case PixelFormat::BC6H_Uf16:
|
||||
case PixelFormat::BC6H_Sf16:
|
||||
case PixelFormat::BC7_Typeless:
|
||||
case PixelFormat::BC7_UNorm:
|
||||
return PixelFormat::R16G16B16A16_Float; // TODO: ASTC HDR
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidPlatformTools::LoadCache(CookingData& data, IBuildCache* cache, const Span<byte>& bytes)
|
||||
{
|
||||
const auto platformSettings = AndroidPlatformSettings::Get();
|
||||
bool invalidTextures = true;
|
||||
if (bytes.Length() == sizeof(AndroidPlatformCache))
|
||||
{
|
||||
auto* platformCache = (AndroidPlatformCache*)bytes.Get();
|
||||
invalidTextures = platformCache->TexturesQuality != platformSettings->TexturesQuality;
|
||||
}
|
||||
if (invalidTextures)
|
||||
{
|
||||
LOG(Info, "{0} option has been modified.", TEXT("TexturesQuality"));
|
||||
cache->InvalidateCacheTextures();
|
||||
}
|
||||
}
|
||||
|
||||
Array<byte> AndroidPlatformTools::SaveCache(CookingData& data, IBuildCache* cache)
|
||||
{
|
||||
const auto platformSettings = AndroidPlatformSettings::Get();
|
||||
AndroidPlatformCache platformCache;
|
||||
platformCache.TexturesQuality = platformSettings->TexturesQuality;
|
||||
Array<byte> result;
|
||||
result.Add((const byte*)&platformCache, sizeof(platformCache));
|
||||
return result;
|
||||
}
|
||||
void AndroidPlatformTools::OnBuildStarted(CookingData& data)
|
||||
{
|
||||
// Adjust the cooking output folder to be located inside the Gradle assets directory
|
||||
|
||||
@@ -30,6 +30,8 @@ public:
|
||||
PlatformType GetPlatform() const override;
|
||||
ArchitectureType GetArchitecture() const override;
|
||||
PixelFormat GetTextureFormat(CookingData& data, TextureBase* texture, PixelFormat format) override;
|
||||
void LoadCache(CookingData& data, IBuildCache* cache, const Span<byte>& bytes) override;
|
||||
Array<byte> SaveCache(CookingData& data, IBuildCache* cache) override;
|
||||
void OnBuildStarted(CookingData& data) override;
|
||||
bool OnPostProcess(CookingData& data) override;
|
||||
};
|
||||
|
||||
@@ -66,11 +66,13 @@ namespace
|
||||
return result;
|
||||
}
|
||||
|
||||
PixelFormat GetQualityTextureFormat(bool sRGB)
|
||||
PixelFormat GetQualityTextureFormat(bool sRGB, PixelFormat format)
|
||||
{
|
||||
const auto platformSettings = iOSPlatformSettings::Get();
|
||||
switch (platformSettings->TexturesQuality)
|
||||
{
|
||||
case iOSPlatformSettings::TextureQuality::Uncompressed:
|
||||
return PixelFormatExtensions::FindUncompressedFormat(format);
|
||||
case iOSPlatformSettings::TextureQuality::ASTC_High:
|
||||
return sRGB ? PixelFormat::ASTC_4x4_UNorm_sRGB : PixelFormat::ASTC_4x4_UNorm;
|
||||
case iOSPlatformSettings::TextureQuality::ASTC_Medium:
|
||||
@@ -78,7 +80,7 @@ namespace
|
||||
case iOSPlatformSettings::TextureQuality::ASTC_Low:
|
||||
return sRGB ? PixelFormat::ASTC_8x8_UNorm_sRGB : PixelFormat::ASTC_8x8_UNorm;
|
||||
default:
|
||||
CRASH;
|
||||
return format;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,12 +124,12 @@ PixelFormat iOSPlatformTools::GetTextureFormat(CookingData& data, TextureBase* t
|
||||
case PixelFormat::BC3_UNorm:
|
||||
case PixelFormat::BC4_UNorm:
|
||||
case PixelFormat::BC5_UNorm:
|
||||
return GetQualityTextureFormat(false);
|
||||
return GetQualityTextureFormat(false, format);
|
||||
case PixelFormat::BC1_UNorm_sRGB:
|
||||
case PixelFormat::BC2_UNorm_sRGB:
|
||||
case PixelFormat::BC3_UNorm_sRGB:
|
||||
case PixelFormat::BC7_UNorm_sRGB:
|
||||
return GetQualityTextureFormat(true);
|
||||
return GetQualityTextureFormat(true, format);
|
||||
case PixelFormat::BC4_SNorm:
|
||||
return PixelFormat::R8_SNorm;
|
||||
case PixelFormat::BC5_SNorm:
|
||||
@@ -137,7 +139,7 @@ PixelFormat iOSPlatformTools::GetTextureFormat(CookingData& data, TextureBase* t
|
||||
case PixelFormat::BC6H_Sf16:
|
||||
case PixelFormat::BC7_Typeless:
|
||||
case PixelFormat::BC7_UNorm:
|
||||
return PixelFormat::R16G16B16A16_Typeless; // TODO: ASTC HDR
|
||||
return PixelFormat::R16G16B16A16_Float; // TODO: ASTC HDR
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
#include "Engine/Graphics/Textures/TextureData.h"
|
||||
#include "Engine/Graphics/Materials/MaterialShader.h"
|
||||
#include "Engine/Graphics/PixelFormatExtensions.h"
|
||||
#include "Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.h"
|
||||
#include "Engine/Engine/Base/GameBase.h"
|
||||
#include "Engine/Engine/Globals.h"
|
||||
@@ -643,6 +644,7 @@ bool ProcessTextureBase(CookAssetsStep::AssetCookData& data)
|
||||
const auto& assetHeader = asset->StreamingTexture()->GetHeader();
|
||||
const auto format = asset->Format();
|
||||
const auto targetFormat = data.Data.Tools->GetTextureFormat(data.Data, asset, format);
|
||||
CHECK_RETURN(!PixelFormatExtensions::IsTypeless(targetFormat), true);
|
||||
const auto streamingSettings = StreamingSettings::Get();
|
||||
int32 mipLevelsMax = GPU_MAX_TEXTURE_MIP_LEVELS;
|
||||
if (assetHeader->TextureGroup >= 0 && assetHeader->TextureGroup < streamingSettings->TextureGroups.Count())
|
||||
|
||||
@@ -915,9 +915,9 @@ PixelFormat PixelFormatExtensions::MakeTypelessUNorm(const PixelFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
PixelFormat PixelFormatExtensions::FindShaderResourceFormat(const PixelFormat format, bool isSRGB)
|
||||
PixelFormat PixelFormatExtensions::FindShaderResourceFormat(const PixelFormat format, bool sRGB)
|
||||
{
|
||||
if (isSRGB)
|
||||
if (sRGB)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
@@ -1000,3 +1000,55 @@ PixelFormat PixelFormatExtensions::FindDepthStencilFormat(const PixelFormat form
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
PixelFormat PixelFormatExtensions::FindUncompressedFormat(PixelFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PixelFormat::BC1_Typeless:
|
||||
case PixelFormat::BC2_Typeless:
|
||||
case PixelFormat::BC3_Typeless:
|
||||
return PixelFormat::R8G8B8A8_Typeless;
|
||||
case PixelFormat::BC1_UNorm:
|
||||
case PixelFormat::BC2_UNorm:
|
||||
case PixelFormat::BC3_UNorm:
|
||||
return PixelFormat::R8G8B8A8_UNorm;
|
||||
case PixelFormat::BC1_UNorm_sRGB:
|
||||
case PixelFormat::BC2_UNorm_sRGB:
|
||||
case PixelFormat::BC3_UNorm_sRGB:
|
||||
return PixelFormat::R8G8B8A8_UNorm_sRGB;
|
||||
case PixelFormat::BC4_Typeless:
|
||||
return PixelFormat::R8_Typeless;
|
||||
case PixelFormat::BC4_UNorm:
|
||||
return PixelFormat::R8_UNorm;
|
||||
case PixelFormat::BC4_SNorm:
|
||||
return PixelFormat::R8_SNorm;
|
||||
case PixelFormat::BC5_Typeless:
|
||||
return PixelFormat::R16G16_Typeless;
|
||||
case PixelFormat::BC5_UNorm:
|
||||
return PixelFormat::R16G16_UNorm;
|
||||
case PixelFormat::BC5_SNorm:
|
||||
return PixelFormat::R16G16_SNorm;
|
||||
case PixelFormat::BC7_Typeless:
|
||||
case PixelFormat::BC6H_Typeless:
|
||||
return PixelFormat::R16G16B16A16_Typeless;
|
||||
case PixelFormat::BC7_UNorm:
|
||||
case PixelFormat::BC6H_Uf16:
|
||||
case PixelFormat::BC6H_Sf16:
|
||||
return PixelFormat::R16G16B16A16_Float;
|
||||
case PixelFormat::BC7_UNorm_sRGB:
|
||||
return PixelFormat::R16G16B16A16_UNorm;
|
||||
case PixelFormat::ASTC_4x4_UNorm:
|
||||
case PixelFormat::ASTC_6x6_UNorm:
|
||||
case PixelFormat::ASTC_8x8_UNorm:
|
||||
case PixelFormat::ASTC_10x10_UNorm:
|
||||
return PixelFormat::R8G8B8A8_UNorm;
|
||||
case PixelFormat::ASTC_4x4_UNorm_sRGB:
|
||||
case PixelFormat::ASTC_6x6_UNorm_sRGB:
|
||||
case PixelFormat::ASTC_8x8_UNorm_sRGB:
|
||||
case PixelFormat::ASTC_10x10_UNorm_sRGB:
|
||||
return PixelFormat::R8G8B8A8_UNorm_sRGB;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
/// <param name="format">The <see cref="PixelFormat"/>.</param>
|
||||
/// <param name="partialTypeless">Enable/disable partially typeless formats.</param>
|
||||
/// <returns><c>true</c> if the specified <see cref="PixelFormat"/> is Typeless; otherwise, <c>false</c>.</returns>
|
||||
API_FUNCTION() static bool IsTypeless(PixelFormat format, bool partialTypeless);
|
||||
API_FUNCTION() static bool IsTypeless(PixelFormat format, bool partialTypeless = true);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the <see cref="PixelFormat"/> is valid.
|
||||
@@ -215,7 +215,8 @@ public:
|
||||
API_FUNCTION() static PixelFormat MakeTypelessUNorm(PixelFormat format);
|
||||
|
||||
public:
|
||||
static PixelFormat FindShaderResourceFormat(PixelFormat format, bool bSRGB);
|
||||
static PixelFormat FindShaderResourceFormat(PixelFormat format, bool sRGB);
|
||||
static PixelFormat FindUnorderedAccessFormat(PixelFormat format);
|
||||
static PixelFormat FindDepthStencilFormat(PixelFormat format);
|
||||
static PixelFormat FindUncompressedFormat(PixelFormat format);
|
||||
};
|
||||
|
||||
@@ -297,7 +297,7 @@ Task* StreamingTexture::UpdateAllocation(int32 residency)
|
||||
if (texture->Init(desc))
|
||||
{
|
||||
Streaming.Error = true;
|
||||
LOG(Error, "Cannot allocate texture {0}.", ToString());
|
||||
LOG(Error, "Cannot allocate texture {0}.", texture->GetName());
|
||||
}
|
||||
if (allocatedResidency != 0)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,24 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
AutoRotation,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The output textures quality (compression).
|
||||
/// </summary>
|
||||
API_ENUM() enum class TextureQuality
|
||||
{
|
||||
// Raw image data without any compression algorithm. Mostly for testing or compatibility.
|
||||
Uncompressed,
|
||||
// ASTC 4x4 block compression.
|
||||
API_ENUM(Attributes="EditorDisplay(null, \"ASTC High\")")
|
||||
ASTC_High,
|
||||
// ASTC 6x6 block compression.
|
||||
API_ENUM(Attributes="EditorDisplay(null, \"ASTC Medium\")")
|
||||
ASTC_Medium,
|
||||
// ASTC 8x8 block compression.
|
||||
API_ENUM(Attributes="EditorDisplay(null, \"ASTC Low\")")
|
||||
ASTC_Low,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The application package name (eg. com.company.product). Custom tokens: ${PROJECT_NAME}, ${COMPANY_NAME}.
|
||||
/// </summary>
|
||||
@@ -66,6 +84,12 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
API_FIELD(Attributes = "EditorOrder(110), EditorDisplay(\"General\")")
|
||||
ScreenOrientation DefaultOrientation = ScreenOrientation::AutoRotation;
|
||||
|
||||
/// <summary>
|
||||
/// The output textures quality (compression).
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(500), EditorDisplay(\"General\")")
|
||||
TextureQuality TexturesQuality = TextureQuality::ASTC_Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Custom icon texture to use for the application (overrides the default one).
|
||||
/// </summary>
|
||||
|
||||
@@ -51,15 +51,17 @@ API_CLASS(Sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
/// </summary>
|
||||
API_ENUM() enum class TextureQuality
|
||||
{
|
||||
// Raw image data without any compression algorithm. Mostly for testing or compatibility.
|
||||
Uncompressed,
|
||||
// ASTC 4x4 block compression.
|
||||
API_ENUM(Attributes="EditorDisplay(null, \"ASTC High\")")
|
||||
ASTC_High = 0,
|
||||
ASTC_High,
|
||||
// ASTC 6x6 block compression.
|
||||
API_ENUM(Attributes="EditorDisplay(null, \"ASTC Medium\")")
|
||||
ASTC_Medium = 1,
|
||||
ASTC_Medium,
|
||||
// ASTC 8x8 block compression.
|
||||
API_ENUM(Attributes="EditorDisplay(null, \"ASTC Low\")")
|
||||
ASTC_Low = 2,
|
||||
ASTC_Low,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user