// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "RawBuffer.h" #include "Device/DeviceBuffer.h" #include "BlobRef.h" #include "Helper/DataUtil.h" #include "2D/TextureHelper.h" class Device; class RawBuffer; class BlobTransform; class Blobber; struct ResourceBindInfo; typedef TUniqueFunction BlobReadyCallback; typedef cti::continuable AsyncBlobResultPtr; typedef std::shared_ptr BlobPtr; typedef std::unique_ptr BlobUPtr; typedef std::weak_ptr BlobPtrW; typedef std::vector BlobPtrVec; typedef std::vector BlobPtrWVec; #if DEBUG_BLOB_REF_KEEPING == 1 struct DebugBlobLock { public: DebugBlobLock(); ~DebugBlobLock(); }; #endif class TEXTUREGRAPHENGINE_API Blob : public std::enable_shared_from_this { friend class Blobber; friend class TiledBlob; friend class TiledBlob_Promise; public: static const char* LODTransformName; typedef std::vector OwnerList; typedef std::vector> LinkedBlobsVec; protected: DeviceBufferRef Buffer; /// Device buffer that is attached to this blob bool bIsFinalised = false; /// Whether the promise has been finalised or not int32 ReplayCount = 0; /// For debug purpose, Incremented when replaying a job and regenerating the content of the blob. FDateTime FinaliseTS = FDateTime::Now(); /// Time when the blob was finalised BlobPtrWVec LODLevels; /// The mip chain for this blob (for textures). Can also be Mesh data with fewer triangles etc. Doesn't matter to us BlobPtr MinMax; /// The blob that's used for calculating min/max std::shared_ptr MinValue; /// Extracted min value (this is not always present) std::shared_ptr MaxValue; /// Extracted min value (this is not always present) BlobPtr Histogram; /// The blob that's used for storing histogram data. not always have a histogram only created when required. BlobPtrW LODParent; /// The parent of this blob. Essentially the blob that was used to generate THIS lod Level BlobPtrW LODSource; /// The original source of this blob, the mip Level 0 bool bIsLODLevel = false; /// Whether this blob already represents an LOD'd blob LinkedBlobsVec LinkedBlobs; /// Blobs that are linked to this tiled blob. These are objects that are /// uniquely created within the system but eventually resolve to the same /// tiled blob. We need to ensure that these are resolved correctly /// so that if some object is holding a pointer to a particular TiledBlob_Promise /// it gets the same view upon the completion. /// This is usually very uncommon with Blobs but more of a possibility with TiledBlob_Promise /// but we need to ensure that it works correctly for all blobs #if DEBUG_BLOB_REF_KEEPING == 1 OwnerList _owners; /// The TiledBlobs that contain this blob as a tile virtual void AddTiledOwner(BlobPtrW owner); #endif Blob(); virtual void OnFinaliseInternal(BlobReadyCallback callback) const; virtual void ResetBuffer(); virtual void Touch(uint64 BatchId); virtual void UpdateAccessInfo(uint64 batchId); virtual void SetHash(CHashPtr Hash); virtual void UpdateLinkedBlobs(bool bDoFinalise); virtual void AddLinkedBlob(BlobPtr LinkedBlob); virtual void FinaliseFrom(Blob* RHS); virtual void SyncWith(Blob* RHS); public: Blob(DeviceBufferRef InBuffer); Blob(const BufferDescriptor& InDesc, CHashPtr InHash); Blob(const Blob& InBlob) = delete; /// non-copyable virtual ~Blob(); virtual AsyncBufferResultPtr Bind(const BlobTransform* Transform, const ResourceBindInfo& BindInfo); virtual AsyncBufferResultPtr Unbind(const BlobTransform* Transform, const ResourceBindInfo& BindInfo); virtual bool IsValid() const; virtual bool IsNull() const; virtual CHashPtr Hash() const; //virtual void SetHash(CHashPtr hash); virtual AsyncBufferResultPtr Flush(const ResourceBindInfo& BindInfo); virtual AsyncPrepareResult PrepareForWrite(const ResourceBindInfo& BindInfo); #if 0 /// TODO /// Do we really need this? virtual AsyncBufferResultPtr PrepareForWrite(const ResourceBindInfo& BindInfo); #endif virtual FString DisplayName() const; virtual bool IsFinalised() const { return bIsFinalised; } virtual bool IsTiled() const { return false; } virtual bool CanCalculateHash() const { return IsFinalised(); } virtual void FinaliseNow(bool bNoCalcHash, CHashPtr FixedHash); virtual AsyncBufferResultPtr Finalise(bool bNoCalcHash, CHashPtr FixedHash); virtual AsyncRawBufferPtr Raw(); /// SLOW: Read doc for DeviceBuffer::Raw() in DeviceBuffer.h virtual AscynCHashPtr CalcHash(); /// SLOW: Because calls Raw() underneath. Don't use directly virtual FString& Name() { check(Buffer); return Buffer->GetName(); } virtual const FString& Name() const { check(Buffer); return Buffer->GetName(); } virtual const BufferDescriptor& GetDescriptor() const { /*check(_buffer);*/ return Buffer->Descriptor(); } virtual AsyncBlobResultPtr OnFinalise() const; virtual AsyncDeviceBufferRef TransferTo(Device* TargetDevice); virtual DeviceBufferRef GetBufferRef() const; ////////////////////////////////////////////////////////////////////////// /// Min/Max related ////////////////////////////////////////////////////////////////////////// virtual BlobPtr GetMinMaxBlob(); virtual void SetMinMax(BlobPtr InMinMax); virtual float GetMinValue() const; virtual float GetMaxValue() const; virtual bool HasMinMax() const; ////////////////////////////////////////////////////////////////////////// /// LOD/MipMaps related ////////////////////////////////////////////////////////////////////////// virtual BlobPtrW GetLODLevel(int32 Level); virtual bool HasLODLevels() const; virtual bool HasLODLevel(int32 Index) const; virtual int32 NumLODLevels() const; virtual void SetLODLevel(int32 Level, BlobPtr LODBlob, BlobPtrW LODParentBlob, BlobPtrW LODSourceBlob, bool bAddToBlobber); BlobPtr GetHistogram() const; ////////////////////////////////////////////////////////////////////////// /// Ownership related ////////////////////////////////////////////////////////////////////////// #if DEBUG_BLOB_REF_KEEPING == 1 virtual void AddOwner(BlobPtrW owner); virtual void RemoveOwner(BlobPtrW owner); void RemoveOwner(Blob* owner); virtual bool HasOwner(BlobPtrW owner); bool HasOwner(Blob* owner); virtual OwnerList::iterator FindOwner(BlobPtrW owner); OwnerList::iterator FindOwner(Blob* owner); virtual bool HasBlobAsTile(Blob* blob) const { return false; }; #endif ////////////////////////////////////////////////////////////////////////// /// Inline function ////////////////////////////////////////////////////////////////////////// FORCEINLINE uint32 GetWidth() const { return GetDescriptor().Width; } FORCEINLINE uint32 GetHeight() const { return GetDescriptor().Height; } FORCEINLINE bool IsWellDefined() { return !IsLateBound() && GetWidth() > 0 && GetHeight() > 0; } //FORCEINLINE const DeviceBufferRef& Buffer() const { return _buffer; } FORCEINLINE DeviceType GetDeviceType() const { return Buffer.GetDeviceType(); } FORCEINLINE int32 GetReplayCount() const { return ReplayCount; } /// For debug purpose, report the replay number FORCEINLINE const FDateTime& FinaliseTimestamp() const { return FinaliseTS; } FORCEINLINE bool IsLateBound() const { return GetDescriptor().Format == BufferFormat::LateBound; } FORCEINLINE BlobPtrW GetLODParent() const { return LODParent; } FORCEINLINE BlobPtrW GetLODSource() const { return LODSource; } FORCEINLINE bool IsLODLevel() const { return bIsLODLevel; } FORCEINLINE bool IsTransient() const { bool TransientBuffer = false; if (Buffer && !Buffer.IsValid()) TransientBuffer = Buffer->IsTransient(); return TransientBuffer || GetDescriptor().bIsTransient; } //Sets the histogram of the blob FORCEINLINE void SetHistogram(BlobPtr InHistogram) { check(!Histogram); Histogram = InHistogram; } //Check if blob already has a histogram FORCEINLINE bool HasHistogram() const { return Histogram != nullptr; } ////////////////////////////////////////////////////////////////////////// /// Static functions ////////////////////////////////////////////////////////////////////////// static CHashPtr CalculateMipHash(CHashPtr MainHash, int32 Level); static CHashPtrVec CalculateMipHashes(CHashPtr MainHash, CHashPtr ParentHash, int32 Level); }; typedef T_BlobRef BlobRef; typedef T_Tiles BlobPtrTiles;