Files
UnrealEngine/Engine/Plugins/TextureGraph/Source/TextureGraphEngine/Data/RawBuffer.h
2025-05-18 13:04:45 +08:00

233 lines
9.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Helper/DataUtil.h"
THIRD_PARTY_INCLUDES_START
#include "continuable/continuable.hpp"
THIRD_PARTY_INCLUDES_END
#include <set>
#include <PixelFormat.h>
#include <Engine/Texture.h>
enum class BufferFormat
{
Byte,
Half,
Float,
Short,
Int,
Count,
Auto = -1, /// Automatically deduce
Custom = -2,
LateBound = -3, /// The Format is unknown at the time and will
/// be known after some async operation has finished
/// Please don't change this value
};
enum class BufferType
{
Generic,
Image,
Mesh,
MeshDetail
};
//////////////////////////////////////////////////////////////////////////
/// BufferDescriptor Metadata Defs
/// Some standardised metadata defs that are used very often. This is not
/// meant to be a comprehensive repository. Other systems can make
/// assumptions and have their own names without having them defined over here.
//////////////////////////////////////////////////////////////////////////
struct RawBufferMetadataDefs
{
//////////////////////////////////////////////////////////////////////////
/// FX related metadata
//////////////////////////////////////////////////////////////////////////
static const FString G_FX_UAV;
//////////////////////////////////////////////////////////////////////////
/// CPU related metadata
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/// Semantic metadata
//////////////////////////////////////////////////////////////////////////
static const FString G_LAYER_MASK;
};
//////////////////////////////////////////////////////////////////////////
struct TEXTUREGRAPHENGINE_API BufferDescriptor
{
typedef std::set<FString> BufferMetadata;
FString Name; /// The name of the buffer
uint32 Width = 0; /// Width of the buffer in terms of number of points
uint32 Height = 0; /// Height of the buffer in terms of number of points
uint32 ItemsPerPoint = 0; /// How many items of Type BufferFormat per point
BufferFormat Format = BufferFormat::Auto; /// What is the Type of each item in the buffer
BufferType Type = BufferType::Image; /// Buffer Type. This is mostly used for debugging
FLinearColor DefaultValue = FLinearColor::Black; /// The default value of the blob values
bool bIsSRGB = false;
bool bIsTransient = false; /// Whether this is a transient buffer
bool bMipMaps = false; /// Enable mip maps for this buffer
BufferMetadata Metadata; /// The metadata associated with this buffer descriptor
HashType HashValue() const;
HashType FormatHashValue() const;
static const char* FormatToString(BufferFormat InFormat);
BufferDescriptor() {}
BufferDescriptor(uint32 InWidth, uint32 InHeight, uint32 InItemsPerPoint,
BufferFormat InFormat = BufferFormat::Float, FLinearColor InDefaultValue = FLinearColor::Black, BufferType InType = BufferType::Image, bool bInMipMaps = false, bool bInSRGB = false);
static EPixelFormat BufferPixelFormat(BufferFormat InFormat, uint32 InItemsPerPoint);
static BufferFormat BufferFormatFromPixelFormat(EPixelFormat PixelFormat);
static size_t BufferFormatSize(BufferFormat InFormat);
static ETextureSourceFormat TextureSourceFormat(BufferFormat InFormat, uint32 InItemsPerPoint);
static BufferDescriptor Combine(const BufferDescriptor& Desc1, const BufferDescriptor& Desc2);
static BufferDescriptor CombineWithPreference(const BufferDescriptor* BaseDesc, const BufferDescriptor* OverrideDesc, const BufferDescriptor* RefDesc);
ETextureSourceFormat TextureSourceFormat() const;
bool IsValid() const;
bool IsFinal() const;
FORCEINLINE size_t FormatSize() const { return BufferDescriptor::BufferFormatSize(Format); }
FORCEINLINE size_t Pitch() const { return Width * FormatSize() * ItemsPerPoint; }
FORCEINLINE size_t Size() const { return Pitch() * Height; }
FORCEINLINE EPixelFormat PixelFormat() const { return BufferDescriptor::BufferPixelFormat(Format, ItemsPerPoint); }
FORCEINLINE bool HasMetadata(const FString& meta) const { return Metadata.find(meta) != Metadata.end(); }
FORCEINLINE bool HasMetadata(FString&& meta) const { return Metadata.find(meta) != Metadata.end(); }
FORCEINLINE bool IsLateBound() const { return Format == BufferFormat::LateBound; }
FORCEINLINE bool IsAuto() const { return Format == BufferFormat::Auto; }
FORCEINLINE bool IsAutoWidth() const { return Width <= 0; }
FORCEINLINE bool IsAutoHeight() const { return Height <= 0; }
FORCEINLINE bool IsAutoSize() const { return IsAutoWidth() || IsAutoHeight(); }
void AddMetadata(const FString& meta) { Metadata.insert(meta); };
void AddMetadata(FString&& meta) { Metadata.insert(meta); };
bool operator == (const BufferDescriptor& rhs) const;
bool operator != (const BufferDescriptor& RHS) const;
FORCEINLINE void AllowUAV() { AddMetadata(RawBufferMetadataDefs::G_FX_UAV); }
FORCEINLINE bool RequiresUAV() const { return HasMetadata(RawBufferMetadataDefs::G_FX_UAV); }
};
typedef std::unique_ptr<BufferDescriptor> BufferDescriptorUPtr;
typedef std::shared_ptr<BufferDescriptor> BufferDescriptorPtr;
class RawBuffer;
typedef std::shared_ptr<RawBuffer> RawBufferPtr;
typedef T_Tiles<std::shared_ptr<RawBuffer>> RawBufferPtrTiles;
typedef cti::continuable<RawBufferPtr> AsyncRawBufferPtr;
typedef cti::continuable<RawBuffer*> AsyncRawBufferP;
enum class RawBufferCompressionType
{
None, /// No compression
Auto, /// Automatically choose a compression Format
PNG, /// PNG compression
ZLib, /// ZLib compression
GZip, /// GZip compression
LZ4, /// LZ4 compression
};
class TEXTUREGRAPHENGINE_API RawBuffer
{
public:
static const uint64 GMinCompress; /// Must have at least this much data to consider compression.
/// Otherwise, its not worth it
private:
/// Must be fixed size (ideally every member should be 64-bit aligned)
struct FileHeader
{
uint64 Version = sizeof(FileHeader);
uint64 CompressionType;
uint64 CompressedLength = 0;
/// For backwards compatibility Anything that
};
static const RawBufferCompressionType GDefaultCompression;
friend class Device_Mem;
//////////////////////////////////////////////////////////////////////////
/// UnCompressed data
//////////////////////////////////////////////////////////////////////////
const uint8* Data = nullptr; /// The actual raw buffer
uint64 Length = 0; /// The length of the data
BufferDescriptor Desc; /// The buffer descriptor
mutable CHashPtr HashValue; /// The hash for this buffer
bool bIsMemoryAutoManaged = false; // There can be instances where the owner of _data isnt RawBuffer, this check ensures those cases
//////////////////////////////////////////////////////////////////////////
/// Compressed data
//////////////////////////////////////////////////////////////////////////
const uint8* CompressedData = nullptr; /// The compressed data
uint64 CompressedLength = 0; /// Length of the compressed buffer
RawBufferCompressionType CompressionType = RawBufferCompressionType::None; /// What is the Type of compression used
//////////////////////////////////////////////////////////////////////////
/// Disk data (compressed)
//////////////////////////////////////////////////////////////////////////
FString FileName; /// The path where the file data is kept
RawBufferCompressionType ChooseBestCompressionFormat() const;
void FreeUncompressed();
void FreeCompressed();
void FreeDisk();
bool UncompressPNG();
bool UncompressGeneric(FName InName);
bool CompressPNG();
bool CompressGeneric(FName InName, RawBufferCompressionType InType);
AsyncRawBufferP ReadFromFile(bool bDoUncompress = false);
public:
RawBuffer(const uint8* InData, size_t InLength, const BufferDescriptor& InDesc, CHashPtr InHashValue = nullptr, bool bInIsMemoryAutoManaged = false);
explicit RawBuffer(const BufferDescriptor& InDesc);
explicit RawBuffer(const RawBufferPtrTiles& InTiles);
~RawBuffer();
AsyncRawBufferP Compress(RawBufferCompressionType InCompressionType = RawBufferCompressionType::Auto, bool bFreeMemory = true);
AsyncRawBufferP Uncompress(bool bFreeMemory = true);
AsyncRawBufferP WriteToFile(const FString& InFileName, bool bFreeMemory = true);
AsyncRawBufferP LoadRawBuffer(bool bInDoUncompress, bool bFreeMemory = true);
void GetAsLinearColor(TArray<FLinearColor>& Pixels) const;
FLinearColor GetAsLinearColor(int PixelIndex) const;
bool IsPadded() const;
size_t GetUnpaddedSize();
void CopyUnpaddedBytes(uint8* DestData);
//////////////////////////////////////////////////////////////////////////
/// Inline functions
//////////////////////////////////////////////////////////////////////////
FORCEINLINE const uint8* GetData() const { return Data; }
FORCEINLINE size_t GetLength() const { return Length; }
FORCEINLINE CHashPtr Hash() const { return HashValue; }
FORCEINLINE const FString& GetName() const { return Desc.Name; }
FORCEINLINE const BufferDescriptor& GetDescriptor() const { return Desc; }
FORCEINLINE uint32 Width() const { return Desc.Width; }
FORCEINLINE uint32 Height() const { return Desc.Height; }
FORCEINLINE bool IsTransient() const { return Desc.bIsTransient; }
FORCEINLINE bool IsCompressed() const { return CompressedData != nullptr; }
FORCEINLINE bool HasData() const { check(IsInGameThread()); return Data != nullptr; }
};