Files
2025-05-18 13:04:45 +08:00

842 lines
32 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "PixelFormat.h"
#include "Serialization/CompactBinary.h"
class ITargetPlatformSettings;
struct FTextureBuildSettings;
class FChildTextureFormat;
/**
* Structure for texture format compressor capabilities.
* This struct is deprecated - FEncodedTextureExtendedData is used instead.
*/
struct FTextureFormatCompressorCaps
{
FTextureFormatCompressorCaps()
: MaxTextureDimension_DEPRECATED(TNumericLimits<uint32>::Max())
, NumMipsInTail_DEPRECATED(0)
, ExtData_DEPRECATED(0)
{ }
// MaxTextureDimension is never set, remove it
uint32 MaxTextureDimension_DEPRECATED;
uint32 NumMipsInTail_DEPRECATED;
uint32 ExtData_DEPRECATED;
};
/**
* Holds various engine configuration parameters that can affect the output of a build but
* should generally be constant across all texture builds. These are sourced from CVars
* and enums/defines that aren't necessarily visible in all modules.
*
* This structure serializes to compact binary only writing if the values are not default,
* so changing the default initialization without changing the texture build version/guid
* can result in build mismatch.
*
* Created via GenerateTextureEngineParameters() in TextureDerivedDataTask.cpp.
*/
struct FTextureEngineParameters
{
bool bEngineSupportsVolumeTextureStreaming = true; // GEngineSupportsVolumeTextureStreaming
bool bEngineSupportsTexture2DArrayStreaming = true; // GEngineSupportsTexture2DArrayStreaming
int32 NumInlineDerivedMips = 7; // NUM_INLINE_DERIVED_MIPS
};
static bool GetStreamingDisabledForNonVirtualTextureProperties(bool bInCubeMap, bool bInVolumeTexture, bool bInTextureArray, const FTextureEngineParameters& InEngineParameters)
{
if (bInCubeMap)
{
return true;
}
if (bInVolumeTexture && InEngineParameters.bEngineSupportsVolumeTextureStreaming == false)
{
return true;
}
if (bInTextureArray && InEngineParameters.bEngineSupportsTexture2DArrayStreaming == false)
{
return true;
}
return false;
}
// Extra data for an encoded texture.
// This is filled out by platform "child" formats that can potentially tile or otherwise
// reorganize the mip data for use on the target platform. For platforms that use bog standard
// "linear" texture data, this is mostly zeroes, but must still be "Valid" data returned by the
// GetExtendedDataForTexture - notably the MipSizesInBytes.
struct FEncodedTextureExtendedData
{
// Copied from RHIDefinitions.h - we expose here to avoid the include.
static constexpr int32 MAX_TEXTURE_MIP_COUNT=15;
// Some platforms group the smallest mips in to a single bulk chunk of data. This is nonzero
// in such cases and the MipSizesInBytes array is truncated.
int32 NumMipsInTail = 0;
// ExtData is metadata the tiler passes through to the runtime.
uint32 ExtData = 0;
// If true, the mip data can't be assumed to be linear.
bool bIsTiled = false;
// If true, this texture might change layouts if top mips are striped (i.e. LODBias is not zero).
bool bSensitiveToLODBias = false;
// If bSensitiveToLODBias is set, this is the LODBias for this layout.
int8 LODBiasIfSensitive = 0;
// All generators of this structure are required to fill this structure out even if they are
// default linear sizes. For non linear textures these are not trivially calculatable.
// Also note that if the texture is sensitive to LODBias with respect to tiling, the indeces in this
// array that are for mips that would be stripped are present but should be ignored as they don't
// represent anything we can accurately calculate.
TArray<uint64, TInlineAllocator<MAX_TEXTURE_MIP_COUNT>> MipSizesInBytes;
};
/**
* Calculate the number of streaming mips for the given set of texture properties. This must work off
* of properties that can (eventually) be calculated without running a full texture build.
*
* Texture mips are split in to two large groups: streaming and non-streaming (aka "inline"). Note
* that "inline" is sometimes used as a verb to mean "load off of disk and place in our bulk data".
* "Inline" textures are loaded with the texture asset, and streaming textures are loaded on demand.
* Generally, 7 of the smallest mips are inlined, however some platforms pack a lot of mips in to a single
* allocation ("packed mip tail" = NumMipsInTail). Those mips must all be inlined.
*
* This function is used primarily for determining where to put mips in the DDC. Runtime inlining is subject
* to further constraints and must use the GetNumNonStreamingMipsDirect() function.
*
* InNumMips The total mips that the texture contains.
* InExtendedData If the texture is being built for a platform that provides extended data, pass it
* here. For platforms that don't need it (i.e. PC), this should be nullptr.
* InEngineParameters Holds a vairety of engine configuration constants, create with GenerateEngineParameters()
*
*/
static int32 GetNumStreamingMipsDirect(int32 InNumMips, bool bInCubeMap, bool bInVolumeTexture, bool bInTextureArray, const FEncodedTextureExtendedData* InExtendedData, const FTextureEngineParameters& InEngineParameters)
{
bool bAllowStreaming = true;
{
const bool bDisableStreaming = GetStreamingDisabledForNonVirtualTextureProperties(bInCubeMap, bInVolumeTexture, bInTextureArray, InEngineParameters);
if (bDisableStreaming)
bAllowStreaming = false;
}
int32 NumStreamingMips = 0;
if (bAllowStreaming)
{
// Some platforms pack several mips in to a single entry. If this is the case,
// those must be non-streaming.
int32 NumMipsInTail = 0;
if (InExtendedData)
{
NumMipsInTail = InExtendedData->NumMipsInTail;
}
int32 NumInlineMips = FMath::Max(NumMipsInTail, InEngineParameters.NumInlineDerivedMips);
NumStreamingMips = FMath::Max(0, InNumMips - NumInlineMips);
}
return NumStreamingMips;
}
/**
Return how many mips need to be inlined for the given texture properties. This pays attention to runtime
size restrictions and should be used for serializing cooked data.
InNumMips, InTopMipSizeX, InTopMipSizeY must all be sizes _before_ any LOD stripping during cook, with the expectation
that the returned value is verified against the remaining mip count after LOD stripping.
This function is not valid if streaming is disabled for the texture.
*/
static int32 GetNumNonStreamingMipsDirect(int32 InNumMips, int32 InTopMipSizeX, int32 InTopMipSizeY, EPixelFormat InPixelFormat, int32 InNumMipsInTail, int32 InNumInlineDerivedMips)
{
if (InNumMips <= 1)
{
return InNumMips;
}
int32 NumNonStreamingMips = 1;
// Take the min resident limit into account.
if (InNumMipsInTail)
{
// If we have a tail, it can't be broken up so the whole thing must be non streaming.
NumNonStreamingMips = FMath::Max(NumNonStreamingMips, InNumMipsInTail);
}
NumNonStreamingMips = FMath::Max(NumNonStreamingMips, InNumInlineDerivedMips);
NumNonStreamingMips = FMath::Min(NumNonStreamingMips, InNumMips);
if ( RequiresBlock4Alignment(InPixelFormat) )
{
// ensure the top non-streamed mip (and all streamed mips) size is >= BlockSize (and a multiple of block size!)
// note: this is not right for non pow 2; NeverStream should set !bIsStreamingPossible in that case
if ( FMath::IsPowerOfTwo(InTopMipSizeX) && FMath::IsPowerOfTwo(InTopMipSizeY) )
{
// This is not right for textures smaller than 4x4, however such textures are already non-streaming due to
// NumInlineDerivedMips (which is functionally hard coded to 7).
NumNonStreamingMips = FMath::Max<int32>(NumNonStreamingMips, InNumMips - FPlatformMath::FloorLog2(InTopMipSizeX / 4));
NumNonStreamingMips = FMath::Max<int32>(NumNonStreamingMips, InNumMips - FPlatformMath::FloorLog2(InTopMipSizeY / 4));
}
else
{
// should never get here as streaming should be disabled in this case, so we should not hit this branch, but it's not reliable
NumNonStreamingMips = InNumMips;
}
}
return NumNonStreamingMips;
}
// Everything necessary to know the memory layout for an encoded untiled unpacked texture (i.e. enough information
// to describe the texture entirely to a PC hardware API).
// Once a texture gets tiled or gets a packed mip tail, FEncodedTextureEncodedData is additionally
// required to know the memory layout.
struct FEncodedTextureDescription
{
int32 TopMipSizeX;
int32 TopMipSizeY;
int32 TopMipVolumeSizeZ; // This is 1 if bVolumeTexture == false
int32 ArraySlices; // This is 1 if bTextureArray == false (including cubemaps)
EPixelFormat PixelFormat;
uint8 NumMips;
bool bCubeMap;
bool bTextureArray;
bool bVolumeTexture;
typedef TArray<FSharedBuffer, TInlineAllocator<FEncodedTextureExtendedData::MAX_TEXTURE_MIP_COUNT>> FSharedBufferMipChain;
typedef TArray<FUniqueBuffer, TInlineAllocator<FEncodedTextureExtendedData::MAX_TEXTURE_MIP_COUNT>> FUniqueBufferMipChain;
bool operator==(const FEncodedTextureDescription& OtherTextureDescription) const
{
return TopMipSizeX == OtherTextureDescription.TopMipSizeX &&
TopMipSizeY == OtherTextureDescription.TopMipSizeY &&
TopMipVolumeSizeZ == OtherTextureDescription.TopMipVolumeSizeZ &&
ArraySlices == OtherTextureDescription.ArraySlices &&
PixelFormat == OtherTextureDescription.PixelFormat &&
NumMips == OtherTextureDescription.NumMips &&
bCubeMap == OtherTextureDescription.bCubeMap &&
bTextureArray == OtherTextureDescription.bTextureArray &&
bVolumeTexture == OtherTextureDescription.bVolumeTexture;
}
// This returns the SizeZ value that is expected by RHI streamable texture structures. It
// is only used by non-cube texture arrays and volumes, however the cubemap array and cubemap
// values need to be consistent as they are persisted and would cause a DDC determinism issue.
// (note that cubemap arrays are handled in the bTextureArray path).
int32 GetRHIStyleSizeZ(int32 InMipIndex) const
{
return (bVolumeTexture || bTextureArray) ? GetNumSlices_WithDepth(InMipIndex) : 1;
}
// Returns the slice count for usage cases/platform that expect slice count to include
// volume texture depth. InMipIndex only affects volume textures.
int32 GetNumSlices_WithDepth(int32 InMipIndex) const
{
if (bVolumeTexture)
{
check(bTextureArray == false && bCubeMap == false);
check(InMipIndex < NumMips);
return FMath::Max(TopMipVolumeSizeZ >> InMipIndex, 1);
}
check ((bTextureArray && ArraySlices >= 1) || (!bTextureArray && ArraySlices == 1));
int32 Slices = ArraySlices;
if (bCubeMap)
{
Slices *= 6;
}
return Slices;
}
// Returns the slice count for usage cases/platforms that expect slice count to only include
// cubemap/array slices.
int32 GetNumSlices_NoDepth() const
{
if (bVolumeTexture)
{
check(bTextureArray == false && bCubeMap == false);
return 1; // no such thing as a cube volume, or a volume array.
}
check((bTextureArray && ArraySlices >= 1) || (!bTextureArray && ArraySlices == 1));
int32 Slices = ArraySlices;
if (bCubeMap)
{
Slices *= 6;
}
return Slices;
}
int32 GetMipWidth(int32 InMipIndex) const
{
return FMath::Max(TopMipSizeX >> InMipIndex, 1);
}
int32 GetMipHeight(int32 InMipIndex) const
{
return FMath::Max(TopMipSizeY >> InMipIndex, 1);
}
// Always 1 unless volume texture.
int32 GetMipDepth(int32 InMipIndex) const
{
return bVolumeTexture ? FMath::Max(TopMipVolumeSizeZ >> InMipIndex, 1) : 1;
}
static int32 GetMipWidth(int32 InTextureWidth, int32 InMipIndex)
{
return FMath::Max(InTextureWidth >> InMipIndex, 1);
}
static int32 GetMipHeight(int32 InTextureHeight, int32 InMipIndex)
{
return FMath::Max(InTextureHeight >> InMipIndex, 1);
}
static int32 GetMipDepth(int32 InTextureDepth, int32 InMipIndex, bool bInVolumeTexture)
{
return bInVolumeTexture ? FMath::Max(InTextureDepth >> InMipIndex, 1) : 1;
}
// Returns the size of the mip at the given index. Z is 1 unless it's a volume texture.
FIntVector3 GetMipDimensions(int32 InMipIndex) const
{
FIntVector3 Results;
Results.X = GetMipWidth(InMipIndex);
Results.Y = GetMipHeight(InMipIndex);
Results.Z = GetMipDepth(InMipIndex);
return Results;
}
// Returns the byte size of the unpacked/tiled mip. For mip chains that are packed or tiled, use FEncodedTextureExtendedData::MipSizesInBytes.
uint64 GetMipSizeInBytes(int32 InMipIndex) const
{
FIntVector3 MipDims = GetMipDimensions(InMipIndex);
uint64 SliceByteCount = GPixelFormats[PixelFormat].Get2DImageSizeInBytes(MipDims.X, MipDims.Y);
return SliceByteCount * GetNumSlices_WithDepth(InMipIndex);
}
// As GetMipSizeInBytes, except for a single slice of the mip.
uint64 GetMipSliceSizeInBytes(int32 InMipIndex) const
{
FIntVector3 MipDims = GetMipDimensions(InMipIndex);
return GPixelFormats[PixelFormat].Get2DImageSizeInBytes(MipDims.X, MipDims.Y);
}
// Returns the bytes necessary to get to the next row of the current mip
uint64 GetMipSliceRowPitchBytes(int32 InMipIndex) const
{
const uint64 WidthInBlocks = GPixelFormats[PixelFormat].GetBlockCountForWidth(GetMipWidth(InMipIndex));
return WidthInBlocks * GPixelFormats[PixelFormat].BlockBytes;
}
// This is the number of streaming mips without any restrictions associated with block size alignment. It's used
// primarily for where mips go in the DDC.
int32 GetNumStreamingMips(const FEncodedTextureExtendedData* InExtendedData, const FTextureEngineParameters& InEngineParameters) const
{
return GetNumStreamingMipsDirect(NumMips, bCubeMap, bVolumeTexture, bTextureArray, InExtendedData, InEngineParameters);
}
// This is the number of nonstreaming mips that works for cooking and thus is aware of block alignment concerns for runtime use.
// Only call this if streaming is possible.
int32 GetNumNonStreamingMips(const FEncodedTextureExtendedData* InExtendedData, const FTextureEngineParameters& InEngineParameters)
{
return GetNumNonStreamingMipsDirect(NumMips, TopMipSizeX, TopMipSizeY, PixelFormat, InExtendedData ? InExtendedData->NumMipsInTail : 0, InEngineParameters.NumInlineDerivedMips);
}
// Fills out the given array with linear mip sizes for the number of mips this texture has. These sizes are only valid
// if the texture is linear and has no packed mip tail (i.e. no associated FEncodedTextureExtendedData).
void GetLinearMipSizesInBytes(TArray<uint64, TInlineAllocator<FEncodedTextureExtendedData::MAX_TEXTURE_MIP_COUNT>>& OutMipSizesInBytes) const
{
OutMipSizesInBytes.SetNumUninitialized(NumMips);
for (int32 MipIndex = 0; MipIndex < NumMips; MipIndex++)
{
OutMipSizesInBytes[MipIndex] = GetMipSizeInBytes(MipIndex);
}
}
// Convenience function for iterating over the encoded mips when you need to know how many mips are represented. Use as:
//
// for (int32 EncodedMipIndex = 0; EncodedMipIndex < OutMipTailIndex + 1; EncodedMipIndex++)
// {
// int32 MipsRepresentedThisIndex = EncodedMipIndex == OutMipTailIndex ? OutMipsInTail : 1;
// }
//
// This handles mip chains whether or not they have packed mip tails.
// Note GetNumEncodedMips() == OutMipTailIndex + 1
//
void GetEncodedMipIterators(const FEncodedTextureExtendedData* InExtendedData, int32& OutMipTailIndex, int32& OutMipsInTail) const
{
OutMipTailIndex = NumMips - 1;
OutMipsInTail = 1;
if (InExtendedData && InExtendedData->NumMipsInTail > 1)
{
OutMipsInTail = InExtendedData->NumMipsInTail;
OutMipTailIndex = NumMips - OutMipsInTail;
}
}
// Returns the number of mips that actually carry bulk data for this texture. Nominally the number of total mips,
// however some platforms have packed mip tails, which means they still have the total number of mips, but the last
// several are all bundled together for memory savings.
int32 GetNumEncodedMips(const FEncodedTextureExtendedData* InExtendedData) const
{
if (InExtendedData &&
InExtendedData->NumMipsInTail > 1)
{
return NumMips - InExtendedData->NumMipsInTail + 1;
}
return NumMips;
}
// Returns the description _for the single mip level_ (i.e. no further mips)
FEncodedTextureDescription GetDescriptionForMipLevel(const FEncodedTextureExtendedData* InExtendedData, int32 InMipIndex) const
{
check(InMipIndex < NumMips);
FEncodedTextureDescription MipTextureDescription = *this;
FIntVector3 TailFirstMipDims = GetMipDimensions(InMipIndex);
MipTextureDescription.TopMipSizeX = TailFirstMipDims.X;
MipTextureDescription.TopMipSizeY = TailFirstMipDims.Y;
MipTextureDescription.TopMipVolumeSizeZ = TailFirstMipDims.Z;
MipTextureDescription.NumMips = 1;
if (InExtendedData && InExtendedData->NumMipsInTail && InMipIndex >= NumMips - InExtendedData->NumMipsInTail)
{
// we must only ever get the first mip tail index!
check(InMipIndex == NumMips - InExtendedData->NumMipsInTail);
// We want the layout for the entire tail.
MipTextureDescription.NumMips = IntCastChecked<uint8>(InExtendedData->NumMipsInTail);
}
return MipTextureDescription;
}
FEncodedTextureDescription RemoveTopMips(const FEncodedTextureExtendedData* InExtendedData, int32 InRemoveCount) const
{
check(InRemoveCount < NumMips);
FEncodedTextureDescription MipTextureDescription = *this;
FIntVector3 TailFirstMipDims = GetMipDimensions(InRemoveCount);
MipTextureDescription.TopMipSizeX = TailFirstMipDims.X;
MipTextureDescription.TopMipSizeY = TailFirstMipDims.Y;
MipTextureDescription.TopMipVolumeSizeZ = TailFirstMipDims.Z;
MipTextureDescription.NumMips = NumMips - InRemoveCount;
if (InExtendedData && InExtendedData->NumMipsInTail && InRemoveCount >= NumMips - InExtendedData->NumMipsInTail)
{
// we must only ever get the first mip tail index!
check(InRemoveCount == NumMips - InExtendedData->NumMipsInTail);
// We want the layout for the entire tail.
MipTextureDescription.NumMips = IntCastChecked<uint8>(InExtendedData->NumMipsInTail);
}
return MipTextureDescription;
}
};
/**
* Interface for platform formats that consume a linear, unpacked texture that an be built on
* a host platform (e.g. windows) and then tile/pack it as necessary.
*/
class ITextureTiler
{
public:
/**
* The generic texture tiling build function expects the following functions to exist that
* do what they say on the tin.
*
* static const FUtf8StringView GetBuildFunctionNameStatic()
* static FGuid GetBuildFunctionVersionGuid()
*/
/**
* Generate and return any out-of-band data that needs to be saved for a given encoded texture description and LODBias.
*/
virtual FEncodedTextureExtendedData GetExtendedDataForTexture(const FEncodedTextureDescription& InTextureDescription, int8 InLODBias) const = 0;
virtual const FUtf8StringView GetBuildFunctionName() const = 0;
virtual const FUtf8StringView GetDetileBuildFunctionName() const = 0;
/**
InLinearSurfaces must have the necessary input mips for the mip level - i.e. for a packed mip tail,
InMipIndex is the index of the top mip of the tail, and InLinearSurfaces must have all the source mips
for the entire tail.
*/
virtual FSharedBuffer ProcessMipLevel(const FEncodedTextureDescription& InTextureDescription, const FEncodedTextureExtendedData& InExtendedData, TArrayView<FMemoryView> InLinearSurfaces, int32 InMipIndex) const = 0;
/**
* Given a tiled mip chain, detile in to OutLinearMips. For mip tails, OutLinearMips.Num may end up larger than InTiledMips.Num.
* Mips have all slices concatenated together.
*/
virtual bool DetileMipChain(FEncodedTextureDescription::FUniqueBufferMipChain& OutLinearMips, FEncodedTextureDescription::FSharedBufferMipChain InTiledMips, const FEncodedTextureDescription& InTextureDescription, const FEncodedTextureExtendedData& InExtendedData, const FString& InTexturePathName) const
{
return false;
}
};
/**
* Interface for texture compression modules.
*
* Note that if you add any virtual functions to this, they almost certainly need to be plumbed through
* ChildTextureFormat! This is why the Format is passed around - ChildTextureFormat needs it to resolve to
* the base format.
*/
class ITextureFormat
{
public:
/**
* Checks whether this texture format can compress in parallel.
*
* @return true if parallel compression is supported, false otherwise.
*/
virtual bool AllowParallelBuild() const
{
return false;
}
/**
* Return the name of the encoder used for the given format.
*
* Used for debugging and UI.
* */
virtual FName GetEncoderName(FName Format) const = 0;
/**
Exposes whether the format supports the fast/final encode speed switching in project settings.
Needs the Format so that we can thunk through the child texture formats correctly.
*/
virtual bool SupportsEncodeSpeed(FName Format, const ITargetPlatformSettings* TargetPlatform) const
{
return false;
}
/**
* @returns true in case Compress can handle other than RGBA32F image formats
*/
virtual bool CanAcceptNonF32Source(FName Format) const
{
return false;
}
// If the format can decode to RGBA8/RGBA16F, this is the IBuild function name for it.
virtual const FUtf8StringView GetDecodeBuildFunctionName() const
{
return UTF8TEXTVIEW("DecodeUnsupported");
}
/**
* Gets the current version of the specified texture format.
*
* @param Format The format to get the version for.
* @return Version number.
*/
virtual uint16 GetVersion(
FName Format,
const FTextureBuildSettings* BuildSettings = nullptr
) const = 0;
/**
* Gets an optional derived data key string, so that the compressor can
* rely upon the number of mips, size of texture, etc, when compressing the image
*
* @param InBuildSettings Reference to the build settings we are compressing with.
* @param InMipCount Mip count of the physical texture that will be built - 0 for virtual textures.
* @param InMip0Dimensions Mip width/height/slices of the physical texture that will be built - 0s for virtual textures.
* @return A string that will be used with the DDC, the string should be in the format "<DATA>_"
*/
virtual FString GetDerivedDataKeyString(const FTextureBuildSettings& InBuildSettings, int32 InMipCount, const FIntVector3& InMip0Dimensions) const
{
return TEXT("");
}
/**
* Gets the list of supported formats.
*
* @param OutFormats Will hold the list of formats.
*/
virtual void GetSupportedFormats( TArray<FName>& OutFormats ) const = 0;
/**
* Gets the capabilities of the texture compressor.
*
* @param OutCaps Filled with capability properties of texture format compressor.
*/
UE_DEPRECATED(5.1, "Hasn't been used in a while.")
virtual FTextureFormatCompressorCaps GetFormatCapabilities() const { return FTextureFormatCompressorCaps(); }
/**
* Gets the capabilities of the texture compressor.
*
* @param OutCaps Filled with capability properties of texture format compressor.
*/
UE_DEPRECATED(5.1, "Use GetExtendedDataForTexture instead to get the same information without the actual image bits.")
virtual FTextureFormatCompressorCaps GetFormatCapabilitiesEx(const FTextureBuildSettings& BuildSettings, uint32 NumMips, const struct FImage& ExampleImage, bool bImageHasAlphaChannel) const
{
return FTextureFormatCompressorCaps();
}
/**
* Calculate the final/runtime pixel format for this image on this platform
*/
UE_DEPRECATED(5.1, "Use GetEncodedPixelFormat(BuildSettings, bImageHasAlphaChannel) instead")
virtual EPixelFormat GetPixelFormatForImage(const FTextureBuildSettings& BuildSettings, const struct FImage& Image, bool bImageHasAlphaChannel) const
{
return GetEncodedPixelFormat(BuildSettings, bImageHasAlphaChannel);
}
/**
* Returns what the compressed pixel format will be for a given format and the given settings.
*
* bInImageHasAlphaChannel is whether or not to treat the source image format as having an alpha channel,
* independent of whether or not it actually has one.
*/
virtual EPixelFormat GetEncodedPixelFormat(const FTextureBuildSettings& InBuildSettings, bool bInImageHasAlphaChannel) const
{
return PF_Unknown;
}
/**
* Generate and return any out-of-band data that needs to be saved for a given encoded texture description. This is
* for textures that have been transformed in some way for a platform. LODBias is needed because in some cases the tiling
* changes based on the top mip actually given to the hardware.
*/
[[nodiscard]] virtual FEncodedTextureExtendedData GetExtendedDataForTexture(const FEncodedTextureDescription& InTextureDescription, int8 InLODBias) const
{
FEncodedTextureExtendedData ExtendedData;
InTextureDescription.GetLinearMipSizesInBytes(ExtendedData.MipSizesInBytes);
return ExtendedData;
}
// Return true if this format can decode the given pixel format to one of the ERawImageFormats.
virtual bool CanDecodeFormat(EPixelFormat InPixelFormat) const { return false; }
/**
* Decodes an image encoded as a EPixelFormat into something encoded as a ERawImageFormat. This will only be called if CanDecodeFormat returns true.
*/
virtual bool DecodeImage(int32 InSizeX, int32 InSizeY, int32 InNumSlices, EPixelFormat InPixelFormat, bool bInSRGB, const FName& InTextureFormatName, FSharedBuffer InEncodedData, FImage& OutImage, FStringView InTextureName) const
{
return false;
}
/**
* Compresses a single image.
*
* @param Image The input image. Image.RawData may be freed or modified by CompressImage; do not use after calling this.
* @param BuildSettings Build settings.
* @param InMip0Dimensions X/Y = Width/Height; Z = 1 unless volume texture, then its depth
* @param InMip0NumSlicesNoDepth see FEncodedTextureDescription::NumSlices_NoDepth()
* @param InMipIndex Mip index of current image in the overall texture.
* @param InMipCount Total mips this texture will be created with.
* @param DebugTexturePathName The path name of the texture we are building, for debug logging/filtering/dumping.
* @param bImageHasAlphaChannel true if the image has a non-white alpha channel.
* @param OutCompressedMip The compressed image.
* @returns true on success, false otherwise.
*/
virtual bool CompressImage(
const FImage& Image,
const FTextureBuildSettings& BuildSettings,
const FIntVector3& InMip0Dimensions,
int32 InMip0NumSlicesNoDepth,
int32 InMipIndex,
int32 InMipCount,
FStringView DebugTexturePathName,
bool bImageHasAlphaChannel,
struct FCompressedImage2D& OutCompressedImage
) const = 0;
/**
* Compress an image (or images for a miptail) into a single mip blob.
*
* @param Images The input image(s). Image.RawData may be freed or modified by CompressImage; do not use after calling this.
* @param NumImages The number of images (for a miptail, this number should match what was returned in GetExtendedDataForTexture, mostly used for verification)
* @param BuildSettings Build settings.
* @param InMip0Dimensions X/Y = Width/Height; Z = 1 unless volume texture, then its depth
* @param InMip0NumSlicesNoDepth see FEncodedTextureDescription::NumSlices_NoDepth()
* @param InMipIndex Mip index of current image in the overall texture.
* @param InMipCount Total mips this texture will be created with.
* @param DebugTexturePathName The path name of the texture we are building, for debug logging/filtering/dumping.
* @param bImageHasAlphaChannel true if the image has a non-white alpha channel.
* @param ExtData Extra data that the format may want to have passed back in to each compress call (makes the format class be stateless)
* @param OutCompressedMip The compressed image.
* @returns true on success, false otherwise.
*/
virtual bool CompressImageEx(
const FImage* Images,
const uint32 NumImages,
const FTextureBuildSettings& BuildSettings,
const FIntVector3& InMip0Dimensions,
int32 InMip0NumSlicesNoDepth,
int32 InMipIndex,
int32 InMipCount,
FStringView DebugTexturePathName,
bool bImageHasAlphaChannel,
uint32 ExtData,
FCompressedImage2D& OutCompressedImage) const
{
// general case can't handle mip tails
if (Images == nullptr || NumImages > 1)
{
return false;
}
return CompressImage(*Images, BuildSettings, InMip0Dimensions, InMip0NumSlicesNoDepth, InMipIndex, InMipCount, DebugTexturePathName, bImageHasAlphaChannel, OutCompressedImage);
}
/**
* An object produced by PrepareTiling and used by SetTiling and CompressImageTiled.
* This is used as an inheritance base for tiling formats to add their own information.
*/
struct FTilerSettings
{
};
/**
* Compress an image (or images for a miptail) into a single mip blob with device-specific tiling.
*
* @param Image The input image. May be freed!
* @param BuildSettings Build settings.
* @param bImageHasAlphaChannel true if the image has a non-white alpha channel.
* @param DebugTexturePathName The path name of the texture we are building, for debug logging/filtering/dumping.
* @param OutCompressedMip The compressed image.
* @param Tiler The tiler settings.
* @returns true on success, false otherwise.
*/
UE_DEPRECATED(5.6, "Tiling compressors will no longer be supported; compress the mip entirely via CompressImage(Ex) and UE will tile the image afterwards")
virtual bool CompressImageTiled(
const FImage* Images,
uint32 NumImages,
const FTextureBuildSettings& BuildSettings,
FStringView DebugTexturePathName,
bool bImageHasAlphaChannel,
TSharedPtr<FTilerSettings>& TilerSettings,
struct FCompressedImage2D& OutCompressedImage) const
{
unimplemented();
return false;
}
/**
* Whether device-specific tiling is supported by the compressor.
*
* @param BuildSettings Build settings.
* @returns true if tiling is supported, false if it must be done by the caller
*
*/
UE_DEPRECATED(5.6, "Tiling compressors will no longer be supported; compress the mip entirely via CompressImage(Ex) and UE will tile the image afterwards")
virtual bool SupportsTiling() const
{
return false;
}
/**
* Prepares to compresses a single image with tiling. The result OutTilerSettings is used by SetTiling and CompressImageTiled.
*
* @param Image The input image.
* @param BuildSettings Build settings.
* @param bImageHasAlphaChannel true if the image has a non-white alpha channel.
* @param OutTilerSettings The tiler settings that will be used by CompressImageTiled and SetTiling.
* @param OutCompressedImage The image to tile.
* @returns true on success, false otherwise.
*/
UE_DEPRECATED(5.6, "Tiling compressors will no longer be supported; compress the mip entirely via CompressImage(Ex) and UE will tile the image afterwards")
virtual bool PrepareTiling(
const FImage* Images,
const uint32 NumImages,
const FTextureBuildSettings& BuildSettings,
bool bImageHasAlphaChannel,
TSharedPtr<FTilerSettings>& OutTilerSettings,
TArray<FCompressedImage2D>& OutCompressedImage
) const
{
unimplemented();
return false;
}
/**
* Sets the tiling settings after device-specific tiling has been performed.
*
* @param BuildSettings Build settings.
* @param TilerSettings The tiler settings produced by PrepareTiling.
* @param ReorderedBlocks The blocks that have been tiled.
* @param NumBlocks The number of blocks.
* @returns true on success, false otherwise.
*/
UE_DEPRECATED(5.6, "Tiling compressors will no longer be supported; compress the mip entirely via CompressImage(Ex) and UE will tile the image afterwards")
virtual bool SetTiling(
const FTextureBuildSettings& BuildSettings,
TSharedPtr<FTilerSettings>& TilerSettings,
const TArray64<uint8>& ReorderedBlocks,
uint32 NumBlocks
) const
{
unimplemented();
return false;
}
/**
* Cleans up the FTilerSettings object once it is finished.
*
* @param BuildSettings Build settings.
* @param TilerSettings The tiler settings object to release.
*/
UE_DEPRECATED(5.6, "Tiling compressors will no longer be supported; compress the mip entirely via CompressImage(Ex) and UE will tile the image afterwards")
virtual void ReleaseTiling(const FTextureBuildSettings& BuildSettings, TSharedPtr<FTilerSettings>& TilerSettings) const
{
unimplemented();
}
/**
* Obtains the current global format config object for this texture format.
*
* This is only ever called during task creation - never in a build worker
* (FormatConfigOverride is empty)
*
* @param BuildSettings Build settings.
* @returns The current format config object or an empty object if no format config is defined for this texture format.
*/
virtual FCbObject ExportGlobalFormatConfig(const FTextureBuildSettings& BuildSettings) const
{
return FCbObject();
}
/**
* If this is an Alternate Texture Format, return the prefix to apply
*/
virtual FString GetAlternateTextureFormatPrefix() const
{
return FString();
}
virtual const FChildTextureFormat* GetChildFormat() const
{
return nullptr;
}
/**
* Identify the latest sdk version for this texture encoder
* (note the SdkVersion is different than the TextureFormat Version)
*/
virtual FName GetLatestSdkVersion() const
{
return FName();
}
UE_DEPRECATED(5.0, "Legacy API - do not use")
virtual bool UsesTaskGraph() const
{
unimplemented();
return true;
}
public:
/** Virtual destructor. */
virtual ~ITextureFormat() { }
};