// 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 #include #include 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 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 BufferDescriptorUPtr; typedef std::shared_ptr BufferDescriptorPtr; class RawBuffer; typedef std::shared_ptr RawBufferPtr; typedef T_Tiles> RawBufferPtrTiles; typedef cti::continuable AsyncRawBufferPtr; typedef cti::continuable 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& 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; } };