From 642c8d2781c27426274ddc5f1cbf53c6b123f6f7 Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Tue, 5 Oct 2021 14:30:40 +0100 Subject: [PATCH] Track owners of reservations in the pool --- .../Private/StevesGameSubsystem.cpp | 4 +- .../Private/StevesTextureRenderTargetPool.cpp | 11 ++-- .../Public/StevesTextureRenderTargetPool.h | 62 ++++++++++++++----- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp b/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp index 9fdaf12..18e22e4 100644 --- a/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp +++ b/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp @@ -254,13 +254,13 @@ FStevesTextureRenderTargetPoolPtr UStevesGameSubsystem::GetTextureRenderTargetPo // On the assumption there won't be *loads* of pools, not worth a map, just iterate for (auto Tex : TextureRenderTargetPools) { - if (Tex->GetPoolName() == Name) + if (Tex->GetName() == Name) return Tex; } if (bAutoCreate) { - FStevesTextureRenderTargetPoolPtr Pool = MakeShared(Name); + FStevesTextureRenderTargetPoolPtr Pool = MakeShared(Name, this); TextureRenderTargetPools.Add(Pool); return Pool; } diff --git a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp index 2b3a0c6..5a93e05 100644 --- a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp +++ b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp @@ -2,9 +2,10 @@ FStevesTextureRenderTargetReservation::~FStevesTextureRenderTargetReservation() { - if (Owner.IsValid() && Texture.IsValid()) + UE_LOG(LogTemp, Warning, TEXT("Releasing texture reservation")); + if (ParentPool.IsValid() && Texture.IsValid()) { - Owner.Pin()->ReleaseTextureReservation(Texture.Get()); + ParentPool.Pin()->ReleaseTextureReservation(Texture.Get()); Texture = nullptr; } } @@ -15,18 +16,18 @@ void FStevesTextureRenderTargetPool::ReleaseTextureReservation(UTextureRenderTar } FStevesTextureRenderTargetReservationPtr FStevesTextureRenderTargetPool::ReserveTexture(FIntPoint Size, - ETextureRenderTargetFormat Format) + ETextureRenderTargetFormat Format, const UObject* Owner) { // TODO return MakeShared(nullptr, this->AsShared()); } -void FStevesTextureRenderTargetPool::RevokeAllReservations() +void FStevesTextureRenderTargetPool::RevokeReservations(const UObject* ForOwner) { // TODO } -void FStevesTextureRenderTargetPool::DrainPool(bool bRevokeReservations) +void FStevesTextureRenderTargetPool::DrainPool(bool bForceAndRevokeReservations) { // TODO } diff --git a/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h index 41ddbdd..b45d217 100644 --- a/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h +++ b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h @@ -1,6 +1,8 @@ #pragma once #include "CoreMinimal.h" +#include "Chaos/AABB.h" +#include "Chaos/AABB.h" #include "Engine/TextureRenderTarget2D.h" typedef TSharedPtr FStevesTextureRenderTargetReservationPtr; @@ -16,14 +18,18 @@ struct STEVESUEHELPERS_API FStevesTextureRenderTargetReservation public: /// The texture. May be null if the pool has forcibly reclaimed the texture prematurely TWeakObjectPtr Texture; - TWeakPtr Owner; - + TWeakPtr ParentPool; + TWeakObjectPtr CurrentOwner; + FStevesTextureRenderTargetReservation() = default; FStevesTextureRenderTargetReservation(UTextureRenderTarget2D* InTexture, - FStevesTextureRenderTargetPoolPtr InOwner) + FStevesTextureRenderTargetPoolPtr InParent, + const UObject* InOwner) : Texture(InTexture), - Owner(InOwner) + ParentPool(InParent), + CurrentOwner(InOwner) + { } @@ -34,13 +40,15 @@ public: /** * 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 { protected: /// The name of the pool. It's possible to have more than one texture pool. - FName PoolName; + FName Name; struct FTextureKey { @@ -65,8 +73,24 @@ protected: }; - TMultiMap> UnreservedTextures; - TArray> ReservedTextures; + TWeakObjectPtr PoolOwner; + TMultiMap UnreservedTextures; + + /// Weak reverse tracking of reservations, mostly for debugging + struct FReservationInfo + { + FTextureKey Key; + TWeakObjectPtr Owner; + TWeakObjectPtr Texture; + + FReservationInfo(const FTextureKey& InKey, const UObject* InOwner, UTextureRenderTarget2D* InTexture) + : Key(InKey), + Owner(InOwner), + Texture(InTexture) + { + } + }; + TArray Reservations; friend struct FStevesTextureRenderTargetReservation; @@ -75,36 +99,40 @@ protected: void ReleaseTextureReservation(UTextureRenderTarget2D* Tex); public: - FStevesTextureRenderTargetPool() = default; - explicit FStevesTextureRenderTargetPool(const FName& PoolName) - : PoolName(PoolName) + explicit FStevesTextureRenderTargetPool(const FName& InName, UObject* InOwner) + : Name(InName), PoolOwner(InOwner) { } - const FName& GetPoolName() const { return PoolName; } + 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); + FStevesTextureRenderTargetReservationPtr ReserveTexture(FIntPoint Size, ETextureRenderTargetFormat Format, const UObject* Owner); /** - * Forcibly revoke all reservations in this pool. Reservations which have been made will have their weak texture - * pointers invalidated. + * 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 RevokeAllReservations(); + void RevokeReservations(const UObject* ForOwner = nullptr); + /** + * * Destroy previously created textures and free the memory. - * @param bRevokeReservations If false, only destroys unreserved textures. If true, destroys reserved textures + * @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 bRevokeReservations = false); + void DrainPool(bool bForceAndRevokeReservations = false); };