From 29ecb3948a340197fbd25aed2abe128507b99de4 Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Mon, 4 Oct 2021 16:23:22 +0100 Subject: [PATCH 1/6] Blocking out render texture pool API --- .../Private/StevesGameSubsystem.cpp | 20 +++++ .../Private/StevesTextureRenderTargetPool.cpp | 32 +++++++ .../Public/StevesGameSubsystem.h | 14 ++++ .../Public/StevesTextureRenderTargetPool.h | 83 +++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp create mode 100644 Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h diff --git a/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp b/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp index a71b48c..9fdaf12 100644 --- a/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp +++ b/Source/StevesUEHelpers/Private/StevesGameSubsystem.cpp @@ -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->GetPoolName() == Name) + return Tex; + } + + if (bAutoCreate) + { + FStevesTextureRenderTargetPoolPtr Pool = MakeShared(Name); + TextureRenderTargetPools.Add(Pool); + return Pool; + } + + return nullptr; + +} + bool UStevesGameSubsystem::FInputModeDetector::ShouldProcessInputEvents() const { diff --git a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp new file mode 100644 index 0000000..2b3a0c6 --- /dev/null +++ b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp @@ -0,0 +1,32 @@ +#include "StevesTextureRenderTargetPool.h" + +FStevesTextureRenderTargetReservation::~FStevesTextureRenderTargetReservation() +{ + if (Owner.IsValid() && Texture.IsValid()) + { + Owner.Pin()->ReleaseTextureReservation(Texture.Get()); + Texture = nullptr; + } +} + +void FStevesTextureRenderTargetPool::ReleaseTextureReservation(UTextureRenderTarget2D* Tex) +{ + // TODO +} + +FStevesTextureRenderTargetReservationPtr FStevesTextureRenderTargetPool::ReserveTexture(FIntPoint Size, + ETextureRenderTargetFormat Format) +{ + // TODO + return MakeShared(nullptr, this->AsShared()); +} + +void FStevesTextureRenderTargetPool::RevokeAllReservations() +{ + // TODO +} + +void FStevesTextureRenderTargetPool::DrainPool(bool bRevokeReservations) +{ + // TODO +} diff --git a/Source/StevesUEHelpers/Public/StevesGameSubsystem.h b/Source/StevesUEHelpers/Public/StevesGameSubsystem.h index 5ad56ce..d7df976 100644 --- a/Source/StevesUEHelpers/Public/StevesGameSubsystem.h +++ b/Source/StevesUEHelpers/Public/StevesGameSubsystem.h @@ -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 TextureRenderTargetPools; + void CreateInputDetector(); void DestroyInputDetector(); void InitTheme(); @@ -198,4 +202,14 @@ public: static void SetBrushFromAtlas(FSlateBrush* Brush, TScriptInterface 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); + }; diff --git a/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h new file mode 100644 index 0000000..bf7dd22 --- /dev/null +++ b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h @@ -0,0 +1,83 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine/TextureRenderTarget2D.h" + +typedef TSharedPtr FStevesTextureRenderTargetReservationPtr; +typedef TSharedPtr 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 Texture; + TWeakPtr Owner; + + FStevesTextureRenderTargetReservation() = default; + + FStevesTextureRenderTargetReservation(UTextureRenderTarget2D* InTexture, + FStevesTextureRenderTargetPoolPtr InOwner) + : Texture(InTexture), + Owner(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. + */ +struct STEVESUEHELPERS_API FStevesTextureRenderTargetPool : public TSharedFromThis +{ + +protected: + /// The name of the pool. It's possible to have more than one texture pool. + FName PoolName; + + 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 ReleaseTextureReservation(UTextureRenderTarget2D* Tex); + +public: + FStevesTextureRenderTargetPool() = default; + + explicit FStevesTextureRenderTargetPool(const FName& PoolName) + : PoolName(PoolName) + { + } + + const FName& GetPoolName() const { return PoolName; } + + /** + * 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 + * @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); + + /** + * Forcibly revoke all reservations in this pool. Reservations which have been made will have their weak texture + * pointers invalidated. + */ + void RevokeAllReservations(); + + /** + * Destroy previously created textures and free the memory. + * @param bRevokeReservations 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); + +}; + From 0a49f5cf74f7ef3346c355036606d631a67d2445 Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Mon, 4 Oct 2021 17:30:07 +0100 Subject: [PATCH 2/6] Storage & lookup for textures --- .../Public/StevesTextureRenderTargetPool.h | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h index bf7dd22..41ddbdd 100644 --- a/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h +++ b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h @@ -42,6 +42,33 @@ protected: /// The name of the pool. It's possible to have more than one texture pool. FName PoolName; + 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(Key.Format)); + } + + }; + + TMultiMap> UnreservedTextures; + TArray> ReservedTextures; + + friend struct FStevesTextureRenderTargetReservation; /// Release a reservation on a texture, allowing it back into the pool /// Protected because only FStevesTextureRenderTargetReservation will need to do this. From 642c8d2781c27426274ddc5f1cbf53c6b123f6f7 Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Tue, 5 Oct 2021 14:30:40 +0100 Subject: [PATCH 3/6] 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); }; From 6b947b6906a4b0fd3cbb9fa52ab16c5544b715b7 Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Tue, 5 Oct 2021 14:30:54 +0100 Subject: [PATCH 4/6] Implement ReserveTexture --- .../Private/StevesTextureRenderTargetPool.cpp | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp index 5a93e05..189fc73 100644 --- a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp +++ b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp @@ -18,8 +18,28 @@ void FStevesTextureRenderTargetPool::ReleaseTextureReservation(UTextureRenderTar FStevesTextureRenderTargetReservationPtr FStevesTextureRenderTargetPool::ReserveTexture(FIntPoint Size, ETextureRenderTargetFormat Format, const UObject* Owner) { - // TODO - return MakeShared(nullptr, this->AsShared()); + const FTextureKey Key {Size, Format}; + UTextureRenderTarget2D* Tex = nullptr; + if (auto Pooled = UnreservedTextures.Find(Key)) + { + Tex = *Pooled; + UnreservedTextures.RemoveSingle(Key, Tex); + } + 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(TextureOwner); + Tex->RenderTargetFormat = Format; + Tex->InitAutoFormat(Size.X, Size.Y); + Tex->UpdateResourceImmediate(true); + } + + // Record reservation + Reservations.Add(FReservationInfo(Key, Owner, Tex)); + + return MakeShared(Tex, this->AsShared(), Owner); } void FStevesTextureRenderTargetPool::RevokeReservations(const UObject* ForOwner) From 5166ce3545df851ed1d1db4c5d961e1ea456627d Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Tue, 5 Oct 2021 14:41:32 +0100 Subject: [PATCH 5/6] Implement ReleaseReservation --- .../Private/StevesTextureRenderTargetPool.cpp | 32 ++++++++++++++++--- .../Public/StevesTextureRenderTargetPool.h | 2 +- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp index 189fc73..18b5077 100644 --- a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp +++ b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp @@ -1,18 +1,39 @@ #include "StevesTextureRenderTargetPool.h" +#include "StevesUEHelpers.h" + FStevesTextureRenderTargetReservation::~FStevesTextureRenderTargetReservation() { - UE_LOG(LogTemp, Warning, TEXT("Releasing texture reservation")); + UE_LOG(LogStevesUEHelpers, Log, TEXT("FStevesTextureRenderTargetReservation: destruction")); if (ParentPool.IsValid() && Texture.IsValid()) { - ParentPool.Pin()->ReleaseTextureReservation(Texture.Get()); + ParentPool.Pin()->ReleaseReservation(Texture.Get()); Texture = nullptr; } } -void FStevesTextureRenderTargetPool::ReleaseTextureReservation(UTextureRenderTarget2D* Tex) +void FStevesTextureRenderTargetPool::ReleaseReservation(UTextureRenderTarget2D* Tex) { - // TODO + 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, @@ -24,6 +45,7 @@ FStevesTextureRenderTargetReservationPtr FStevesTextureRenderTargetPool::Reserve { 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) { @@ -34,6 +56,8 @@ FStevesTextureRenderTargetReservationPtr FStevesTextureRenderTargetPool::Reserve 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 diff --git a/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h index b45d217..c837591 100644 --- a/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h +++ b/Source/StevesUEHelpers/Public/StevesTextureRenderTargetPool.h @@ -96,7 +96,7 @@ protected: 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 ReleaseTextureReservation(UTextureRenderTarget2D* Tex); + void ReleaseReservation(UTextureRenderTarget2D* Tex); public: From 2776233d9d4bdd5657d7635dfe583c2e42c203ed Mon Sep 17 00:00:00 2001 From: Steve Streeting Date: Tue, 5 Oct 2021 15:27:53 +0100 Subject: [PATCH 6/6] Implement revoke / drain pool methods --- .../Private/StevesTextureRenderTargetPool.cpp | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp index 18b5077..6099c20 100644 --- a/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp +++ b/Source/StevesUEHelpers/Private/StevesTextureRenderTargetPool.cpp @@ -1,6 +1,7 @@ #include "StevesTextureRenderTargetPool.h" #include "StevesUEHelpers.h" +#include "Kismet/KismetRenderingLibrary.h" FStevesTextureRenderTargetReservation::~FStevesTextureRenderTargetReservation() { @@ -68,10 +69,32 @@ FStevesTextureRenderTargetReservationPtr FStevesTextureRenderTargetPool::Reserve void FStevesTextureRenderTargetPool::RevokeReservations(const UObject* ForOwner) { - // TODO + 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) { - // TODO + if (bForceAndRevokeReservations) + RevokeReservations(); + + for (auto& TexPair : UnreservedTextures) + { + UKismetRenderingLibrary::ReleaseRenderTarget2D(TexPair.Value); + } + UnreservedTextures.Empty(); }