# Conflicts: # Content/Shaders/GI/DDGI.flax # Content/Shaders/GI/GlobalSurfaceAtlas.flax # Content/Shaders/TAA.flax # Content/Shaders/VolumetricFog.flax # Source/Editor/CustomEditors/Editors/ActorTagEditor.cs # Source/Engine/Core/Config/GraphicsSettings.cpp # Source/Engine/Engine/PostProcessEffect.cs # Source/Engine/Graphics/GPUResourcesCollection.cpp # Source/Engine/Graphics/GPUResourcesCollection.h # Source/Engine/Graphics/PostProcessBase.h # Source/FlaxEngine.Gen.cs
115 lines
2.8 KiB
C++
115 lines
2.8 KiB
C++
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
|
|
|
#include "RenderTargetPool.h"
|
|
#include "GPUDevice.h"
|
|
#include "Engine/Core/Log.h"
|
|
#include "Engine/Engine/Engine.h"
|
|
|
|
struct Entry
|
|
{
|
|
bool IsOccupied;
|
|
GPUTexture* RT;
|
|
uint64 LastFrameTaken;
|
|
uint64 LastFrameReleased;
|
|
uint32 DescriptionHash;
|
|
};
|
|
|
|
namespace
|
|
{
|
|
Array<Entry> TemporaryRTs(64);
|
|
}
|
|
|
|
void RenderTargetPool::Flush(bool force)
|
|
{
|
|
const uint64 framesOffset = 10;
|
|
const uint64 maxReleaseFrame = Engine::FrameCount - framesOffset;
|
|
force |= Engine::ShouldExit();
|
|
|
|
for (int32 i = 0; i < TemporaryRTs.Count(); i++)
|
|
{
|
|
auto& tmp = TemporaryRTs[i];
|
|
|
|
if (!tmp.IsOccupied && (force || (tmp.LastFrameReleased < maxReleaseFrame)))
|
|
{
|
|
// Release
|
|
tmp.RT->DeleteObjectNow();
|
|
TemporaryRTs.RemoveAt(i);
|
|
i--;
|
|
|
|
if (TemporaryRTs.IsEmpty())
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
GPUTexture* RenderTargetPool::Get(const GPUTextureDescription& desc)
|
|
{
|
|
// Find free render target with the same properties
|
|
const uint32 descHash = GetHash(desc);
|
|
for (int32 i = 0; i < TemporaryRTs.Count(); i++)
|
|
{
|
|
auto& tmp = TemporaryRTs[i];
|
|
|
|
if (!tmp.IsOccupied && tmp.DescriptionHash == descHash)
|
|
{
|
|
ASSERT(tmp.RT);
|
|
|
|
// Mark as used
|
|
tmp.IsOccupied = true;
|
|
tmp.LastFrameTaken = Engine::FrameCount;
|
|
return tmp.RT;
|
|
}
|
|
}
|
|
|
|
#if !BUILD_RELEASE
|
|
if (TemporaryRTs.Count() > 2000)
|
|
{
|
|
LOG(Fatal, "Too many textures allocated in RenderTargetPool. Know your limits, sir!");
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
|
|
// Create new rt
|
|
const String name = TEXT("TemporaryRT_") + StringUtils::ToString(TemporaryRTs.Count());
|
|
auto newRenderTarget = GPUDevice::Instance->CreateTexture(name);
|
|
if (newRenderTarget->Init(desc))
|
|
{
|
|
Delete(newRenderTarget);
|
|
LOG(Error, "Cannot create temporary render target. Description: {0}", desc.ToString());
|
|
return nullptr;
|
|
}
|
|
|
|
// Create temporary rt entry
|
|
Entry entry;
|
|
entry.IsOccupied = true;
|
|
entry.LastFrameReleased = 0;
|
|
entry.LastFrameTaken = Engine::FrameCount;
|
|
entry.RT = newRenderTarget;
|
|
entry.DescriptionHash = descHash;
|
|
TemporaryRTs.Add(entry);
|
|
|
|
return newRenderTarget;
|
|
}
|
|
|
|
void RenderTargetPool::Release(GPUTexture* rt)
|
|
{
|
|
if (!rt)
|
|
return;
|
|
|
|
for (int32 i = 0; i < TemporaryRTs.Count(); i++)
|
|
{
|
|
auto& tmp = TemporaryRTs[i];
|
|
|
|
if (tmp.RT == rt)
|
|
{
|
|
// Mark as free
|
|
ASSERT(tmp.IsOccupied);
|
|
tmp.IsOccupied = false;
|
|
tmp.LastFrameReleased = Engine::FrameCount;
|
|
return;
|
|
}
|
|
}
|
|
|
|
LOG(Error, "Trying to release temporary render target which has not been registered in service!");
|
|
}
|