mirror of
https://github.com/sinbad/StevesUEHelpers.git
synced 2025-02-23 09:35:25 +00:00
Merge branch 'rtt-pool'
This commit is contained in:
commit
dee0aad4f3
@ -249,6 +249,26 @@ void UStevesGameSubsystem::SetBrushFromAtlas(FSlateBrush* Brush, TScriptInterfac
|
||||
}
|
||||
}
|
||||
|
||||
FStevesTextureRenderTargetPoolPtr UStevesGameSubsystem::GetTextureRenderTargetPool(FName Name, bool bAutoCreate)
|
||||
{
|
||||
// On the assumption there won't be *loads* of pools, not worth a map, just iterate
|
||||
for (auto Tex : TextureRenderTargetPools)
|
||||
{
|
||||
if (Tex->GetName() == Name)
|
||||
return Tex;
|
||||
}
|
||||
|
||||
if (bAutoCreate)
|
||||
{
|
||||
FStevesTextureRenderTargetPoolPtr Pool = MakeShared<FStevesTextureRenderTargetPool>(Name, this);
|
||||
TextureRenderTargetPools.Add(Pool);
|
||||
return Pool;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool UStevesGameSubsystem::FInputModeDetector::ShouldProcessInputEvents() const
|
||||
{
|
||||
|
100
Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp
Normal file
100
Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include "StevesTextureRenderTargetPool.h"
|
||||
|
||||
#include "StevesUEHelpers.h"
|
||||
#include "Kismet/KismetRenderingLibrary.h"
|
||||
|
||||
FStevesTextureRenderTargetReservation::~FStevesTextureRenderTargetReservation()
|
||||
{
|
||||
UE_LOG(LogStevesUEHelpers, Log, TEXT("FStevesTextureRenderTargetReservation: destruction"));
|
||||
if (ParentPool.IsValid() && Texture.IsValid())
|
||||
{
|
||||
ParentPool.Pin()->ReleaseReservation(Texture.Get());
|
||||
Texture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FStevesTextureRenderTargetPool::ReleaseReservation(UTextureRenderTarget2D* Tex)
|
||||
{
|
||||
if (!Tex)
|
||||
{
|
||||
UE_LOG(LogStevesUEHelpers, Warning, TEXT("FStevesTextureRenderTargetPool: Attempted to release a null texture"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Reservations.Num(); ++i)
|
||||
{
|
||||
const FReservationInfo& R = Reservations[i];
|
||||
if (R.Texture.IsValid() && R.Texture.Get() == Tex)
|
||||
{
|
||||
UE_LOG(LogStevesUEHelpers, Verbose, TEXT("FStevesTextureRenderTargetPool: Released texture reservation on %s"), *Tex->GetName());
|
||||
UnreservedTextures.Add(R.Key, Tex);
|
||||
Reservations.RemoveAtSwap(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogStevesUEHelpers, Warning, TEXT("FStevesTextureRenderTargetPool: Attempted to release a reservation on %s that was not found"), *Tex->GetName());
|
||||
|
||||
}
|
||||
|
||||
FStevesTextureRenderTargetReservationPtr FStevesTextureRenderTargetPool::ReserveTexture(FIntPoint Size,
|
||||
ETextureRenderTargetFormat Format, const UObject* Owner)
|
||||
{
|
||||
const FTextureKey Key {Size, Format};
|
||||
UTextureRenderTarget2D* Tex = nullptr;
|
||||
if (auto Pooled = UnreservedTextures.Find(Key))
|
||||
{
|
||||
Tex = *Pooled;
|
||||
UnreservedTextures.RemoveSingle(Key, Tex);
|
||||
UE_LOG(LogStevesUEHelpers, Verbose, TEXT("FStevesTextureRenderTargetPool: Re-used pooled texture %s"), *Tex->GetName());
|
||||
}
|
||||
else if (Size.X > 0 && Size.Y > 0)
|
||||
{
|
||||
// No existing texture, so create
|
||||
// Texture owner should be a valid UObject that will determine lifespan
|
||||
UObject* TextureOwner = PoolOwner.IsValid() ? PoolOwner.Get() : GetTransientPackage();
|
||||
Tex = NewObject<UTextureRenderTarget2D>(TextureOwner);
|
||||
Tex->RenderTargetFormat = Format;
|
||||
Tex->InitAutoFormat(Size.X, Size.Y);
|
||||
Tex->UpdateResourceImmediate(true);
|
||||
|
||||
UE_LOG(LogStevesUEHelpers, Verbose, TEXT("FStevesTextureRenderTargetPool: Created new texture %s"), *Tex->GetName());
|
||||
}
|
||||
|
||||
// Record reservation
|
||||
Reservations.Add(FReservationInfo(Key, Owner, Tex));
|
||||
|
||||
return MakeShared<FStevesTextureRenderTargetReservation>(Tex, this->AsShared(), Owner);
|
||||
}
|
||||
|
||||
void FStevesTextureRenderTargetPool::RevokeReservations(const UObject* ForOwner)
|
||||
{
|
||||
for (int i = 0; i < Reservations.Num(); ++i)
|
||||
{
|
||||
const FReservationInfo& R = Reservations[i];
|
||||
if (!ForOwner || R.Owner == ForOwner)
|
||||
{
|
||||
if (R.Texture.IsValid())
|
||||
{
|
||||
UE_LOG(LogStevesUEHelpers, Verbose, TEXT("FStevesTextureRenderTargetPool: Revoked texture reservation on %s"), *R.Texture->GetName());
|
||||
UnreservedTextures.Add(R.Key, R.Texture.Get());
|
||||
}
|
||||
// Can't use RemoveAtSwap because it'll change order
|
||||
Reservations.RemoveAt(i);
|
||||
// Adjust index backwards to compensate
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FStevesTextureRenderTargetPool::DrainPool(bool bForceAndRevokeReservations)
|
||||
{
|
||||
if (bForceAndRevokeReservations)
|
||||
RevokeReservations();
|
||||
|
||||
for (auto& TexPair : UnreservedTextures)
|
||||
{
|
||||
UKismetRenderingLibrary::ReleaseRenderTarget2D(TexPair.Value);
|
||||
}
|
||||
UnreservedTextures.Empty();
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
#include "PaperSprite.h"
|
||||
#include "Framework/Application/IInputProcessor.h"
|
||||
#include "StevesHelperCommon.h"
|
||||
#include "StevesTextureRenderTargetPool.h"
|
||||
#include "StevesUI/FocusSystem.h"
|
||||
#include "StevesUI/UiTheme.h"
|
||||
|
||||
@ -14,6 +15,7 @@
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnInputModeChanged, int, PlayerIndex, EInputMode, InputMode);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWindowForegroundChanged, bool, bFocussed);
|
||||
|
||||
/// Entry point for all the top-level features of the helper system
|
||||
UCLASS(Config=Game)
|
||||
class STEVESUEHELPERS_API UStevesGameSubsystem : public UGameInstanceSubsystem
|
||||
{
|
||||
@ -109,6 +111,8 @@ protected:
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
UUiTheme* DefaultUiTheme;
|
||||
|
||||
TArray<FStevesTextureRenderTargetPoolPtr> TextureRenderTargetPools;
|
||||
|
||||
void CreateInputDetector();
|
||||
void DestroyInputDetector();
|
||||
void InitTheme();
|
||||
@ -198,4 +202,14 @@ public:
|
||||
static void SetBrushFromAtlas(FSlateBrush* Brush, TScriptInterface<ISlateTextureAtlasInterface> AtlasRegion,
|
||||
bool bMatchSize);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a pool of texture render targets. If a pool doesn't exist with the given name, it can be created.
|
||||
* @param Name Identifier for the pool.
|
||||
* @param bAutoCreate
|
||||
* @return The pool, or null if it doesn't exist and bAutoCreate is false
|
||||
*/
|
||||
FStevesTextureRenderTargetPoolPtr GetTextureRenderTargetPool(FName Name, bool bAutoCreate = true);
|
||||
|
||||
};
|
||||
|
138
Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h
Normal file
138
Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h
Normal file
@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Chaos/AABB.h"
|
||||
#include "Chaos/AABB.h"
|
||||
#include "Engine/TextureRenderTarget2D.h"
|
||||
|
||||
typedef TSharedPtr<struct FStevesTextureRenderTargetReservation> FStevesTextureRenderTargetReservationPtr;
|
||||
typedef TSharedPtr<struct FStevesTextureRenderTargetPool> FStevesTextureRenderTargetPoolPtr;
|
||||
|
||||
/// Holder for an assigned texture. While this structure exists, the texture will be considered assigned
|
||||
/// and will not be returned from any other request. Once this structure is destroyed the texture will
|
||||
/// be free for re-use. For that reason, only pass this structure around by SharedRef/SharedPtr.
|
||||
/// The texture is held by a weak pointer however, the strong pointer is held by the pool. The texture will continue
|
||||
/// to be available to this reservation except if the pool is told to forcibly release textures.
|
||||
struct STEVESUEHELPERS_API FStevesTextureRenderTargetReservation
|
||||
{
|
||||
public:
|
||||
/// The texture. May be null if the pool has forcibly reclaimed the texture prematurely
|
||||
TWeakObjectPtr<UTextureRenderTarget2D> Texture;
|
||||
TWeakPtr<struct FStevesTextureRenderTargetPool> ParentPool;
|
||||
TWeakObjectPtr<const UObject> CurrentOwner;
|
||||
|
||||
FStevesTextureRenderTargetReservation() = default;
|
||||
|
||||
FStevesTextureRenderTargetReservation(UTextureRenderTarget2D* InTexture,
|
||||
FStevesTextureRenderTargetPoolPtr InParent,
|
||||
const UObject* InOwner)
|
||||
: Texture(InTexture),
|
||||
ParentPool(InParent),
|
||||
CurrentOwner(InOwner)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
~FStevesTextureRenderTargetReservation();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A pool of render target textures. To save pre-creating render textures as assets, and to control the re-use of
|
||||
* these textures at runtime.
|
||||
* A pool needs to be owned by a UObject, which will in turn own the textures and so will ultimately control the
|
||||
* ultimate lifecycle of textures if not released specifically.
|
||||
*/
|
||||
struct STEVESUEHELPERS_API FStevesTextureRenderTargetPool : public TSharedFromThis<FStevesTextureRenderTargetPool>
|
||||
{
|
||||
|
||||
protected:
|
||||
/// The name of the pool. It's possible to have more than one texture pool.
|
||||
FName Name;
|
||||
|
||||
struct FTextureKey
|
||||
{
|
||||
FIntPoint Size;
|
||||
ETextureRenderTargetFormat Format;
|
||||
|
||||
friend bool operator==(const FTextureKey& Lhs, const FTextureKey& RHS)
|
||||
{
|
||||
return Lhs.Size == RHS.Size
|
||||
&& Lhs.Format == RHS.Format;
|
||||
}
|
||||
|
||||
friend bool operator!=(const FTextureKey& Lhs, const FTextureKey& RHS)
|
||||
{
|
||||
return !(Lhs == RHS);
|
||||
}
|
||||
|
||||
friend uint32 GetTypeHash(const FTextureKey& Key)
|
||||
{
|
||||
return HashCombine(GetTypeHash(Key.Size), static_cast<uint32>(Key.Format));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TWeakObjectPtr<UObject> PoolOwner;
|
||||
TMultiMap<FTextureKey, UTextureRenderTarget2D*> UnreservedTextures;
|
||||
|
||||
/// Weak reverse tracking of reservations, mostly for debugging
|
||||
struct FReservationInfo
|
||||
{
|
||||
FTextureKey Key;
|
||||
TWeakObjectPtr<const UObject> Owner;
|
||||
TWeakObjectPtr<UTextureRenderTarget2D> Texture;
|
||||
|
||||
FReservationInfo(const FTextureKey& InKey, const UObject* InOwner, UTextureRenderTarget2D* InTexture)
|
||||
: Key(InKey),
|
||||
Owner(InOwner),
|
||||
Texture(InTexture)
|
||||
{
|
||||
}
|
||||
};
|
||||
TArray<FReservationInfo> Reservations;
|
||||
|
||||
|
||||
friend struct FStevesTextureRenderTargetReservation;
|
||||
/// Release a reservation on a texture, allowing it back into the pool
|
||||
/// Protected because only FStevesTextureRenderTargetReservation will need to do this.
|
||||
void ReleaseReservation(UTextureRenderTarget2D* Tex);
|
||||
|
||||
public:
|
||||
|
||||
explicit FStevesTextureRenderTargetPool(const FName& InName, UObject* InOwner)
|
||||
: Name(InName), PoolOwner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
const FName& GetName() const { return Name; }
|
||||
|
||||
/**
|
||||
* Reserve a texture for use as a render target. This will create a new texture target if needed.
|
||||
* @param Size The dimensions of the texture
|
||||
* @param Format Format of the texture
|
||||
* @param Owner The UObject which will temporarily own this texture (mostly for debugging, this object won't in fact "own" it
|
||||
* as per garbage collection rules, the reference is weak
|
||||
* @return A shared pointer to a structure which holds the reservation for this texture. When that structure is
|
||||
* destroyed, it will release the texture back to the pool.
|
||||
*/
|
||||
FStevesTextureRenderTargetReservationPtr ReserveTexture(FIntPoint Size, ETextureRenderTargetFormat Format, const UObject* Owner);
|
||||
|
||||
/**
|
||||
* Forcibly revoke reservations in this pool, either for all owners or for a specific owner.
|
||||
* Reservations which are revoked will have their weak texture pointers invalidated.
|
||||
* @param ForOwner If null, revoke all reservations for any owner, or if provided, just for a specific owner.
|
||||
*/
|
||||
void RevokeReservations(const UObject* ForOwner = nullptr);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Destroy previously created textures and free the memory.
|
||||
* @param bForceAndRevokeReservations If false, only destroys unreserved textures. If true, destroys reserved textures
|
||||
* as well (the weak pointer on their reservations will cease to be valid)
|
||||
*/
|
||||
void DrainPool(bool bForceAndRevokeReservations = false);
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user