You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/RenderDll/Common/Textures/TextureStreamPool.h

308 lines
7.3 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_TEXTURES_TEXTURESTREAMPOOL_H
#define CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_TEXTURES_TEXTURESTREAMPOOL_H
#pragma once
#define TEXSTRM_USE_FREEPOOL
struct STexPool;
struct STexPoolItemHdr
{
static CryCriticalSection s_sSyncLock;
STexPoolItemHdr* m_Next;
STexPoolItemHdr* m_Prev;
STexPoolItemHdr* m_NextFree;
STexPoolItemHdr* m_PrevFree;
STexPoolItemHdr()
: m_Next(NULL)
, m_Prev(NULL)
, m_NextFree(NULL)
, m_PrevFree(NULL)
{
}
_inline void Unlink();
_inline void Link(STexPoolItemHdr* Before);
_inline void UnlinkFree();
_inline void LinkFree(STexPoolItemHdr* Before);
};
struct STexPoolItem
: STexPoolItemHdr
{
STexPool* const m_pOwner;
CTexture* m_pTex;
CDeviceTexture* const m_pDevTexture;
size_t const m_nDeviceTexSize;
uint32 m_nFreeTick;
uint8 m_nActiveLod;
STexPoolItem (STexPool* pOwner, CDeviceTexture* pDevTexture, size_t devSize);
~STexPoolItem();
bool IsFree() const { return m_NextFree != NULL; }
int GetSize()
{
int nSize = sizeof(*this);
return nSize;
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
pSizer->AddObject(m_pDevTexture);
}
bool IsStillUsedByGPU(uint32 nCurTick);
};
struct STexPool
{
uint16 m_Width;
uint16 m_Height;
uint16 m_nArraySize;
D3DFormat m_eFormat;
size_t m_Size;
STexPoolItemHdr m_ItemsList;
ETEX_Type m_eTT;
uint8 m_nMips;
int m_nItems;
int m_nItemsFree;
~STexPool();
size_t GetSize()
{
size_t nSize = sizeof(*this);
STexPoolItemHdr* pIT = m_ItemsList.m_Next;
while (pIT != &m_ItemsList)
{
nSize += static_cast<STexPoolItem*>(pIT)->GetSize();
pIT = pIT->m_Next;
}
return nSize;
}
uint32 GetNumSlices() const
{
uint32 b = (m_eTT == eTT_Cube) ? 6 : 1;
return b * m_nArraySize;
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
pSizer->AddObject(this, sizeof(*this));
STexPoolItemHdr* pIT = m_ItemsList.m_Next;
while (pIT != &m_ItemsList)
{
pSizer->AddObject(static_cast<STexPoolItem*>(pIT));
pIT = pIT->m_Next;
}
}
};
class CTextureStreamPoolMgr
{
public:
struct SFrameStats
{
SFrameStats()
{
memset(this, 0, sizeof(*this));
}
int nSoftCreates;
int nSoftFrees;
int nHardCreates;
int nHardFrees;
};
struct SPoolStats
{
int nWidth;
int nHeight;
int nMips;
uint32 nFormat;
ETEX_Type eTT;
int nInUse;
int nFree;
int nHardCreatesPerFrame;
int nSoftCreatesPerFrame;
};
public:
CTextureStreamPoolMgr();
~CTextureStreamPoolMgr();
void Flush();
// Fetch and reset last frame stats
#if !defined(_RELEASE)
void EnableStatsComputation(bool bCompute) { m_bComputeStats = bCompute; }
SFrameStats FetchFrameStats()
{
SFrameStats frameStats = m_frameStats;
m_frameStats = SFrameStats();
return frameStats;
}
void FetchPoolStats(std::vector<SPoolStats>& poolStats)
{
CryAutoLock<CryCriticalSection> lock(m_statsLock);
poolStats = m_poolStats;
m_poolStats.clear();
}
#endif
STexPool* GetPool(int nWidth, int nHeight, int nMips, int nArraySize, ETEX_Format eTF, bool bIsSRGB, ETEX_Type eTT);
STexPoolItem* GetPoolItem(int nWidth, int nHeight, int nMips, int nArraySize, ETEX_Format eTF, bool bIsSRGB, ETEX_Type eTT, bool bShouldBeCreated, const char* sName, STextureInfo* pTI = NULL, bool bCanCreate = true, bool bWaitForIdle = true);
void ReleaseItem(STexPoolItem* pItem);
void GarbageCollect(size_t* nCurTexPoolSize, size_t nLowerPoolLimit, int nMaxItemsToFree);
void GetMemoryUsage(ICrySizer* pSizer);
size_t GetInUseSize() const { return m_nDeviceMemInUse; }
size_t GetReservedSize() const { return m_nDeviceMemReserved; }
private:
union TexturePoolKey
{
struct
{
uint64 a, b;
};
struct
{
uint16 nWidth;
uint16 nHeight;
uint32 nFormat;
uint8 nTexType;
uint8 nMips;
uint16 nArraySize;
};
TexturePoolKey(uint16 nWidth, uint16 nHeight, uint32 nFormat, uint8 nTexType, uint8 nMips, uint16 nArraySize)
{
memset(this, 0, sizeof(*this));
this->nWidth = nWidth;
this->nHeight = nHeight;
this->nFormat = nFormat;
this->nTexType = nTexType;
this->nMips = nMips;
this->nArraySize = nArraySize;
}
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
friend bool operator < (const TexturePoolKey& a, const TexturePoolKey& b)
{
if (a.a != b.a)
{
return a.a < b.a;
}
return a.b < b.b;
}
};
enum
{
MaxFreePool = 64,
};
typedef VectorMap<TexturePoolKey, STexPool*> TexturePoolMap;
private:
STexPool* CreatePool(int nWidth, int nHeight, int nMips, int nArraySize, D3DFormat eTF, ETEX_Type eTT);
void FlushFree();
private:
volatile size_t m_nDeviceMemReserved;
volatile size_t m_nDeviceMemInUse;
#if !defined(_RELEASE)
CryCriticalSection m_statsLock;
bool m_bComputeStats;
std::vector<SPoolStats> m_poolStats;
SFrameStats m_frameStats;
#endif
uint32 m_nTick;
TexturePoolMap m_TexturesPools;
STexPoolItemHdr m_FreeTexPoolItems;
#ifdef TEXSTRM_USE_FREEPOOL
void* m_FreePool[MaxFreePool];
size_t m_nFreePoolBegin;
size_t m_nFreePoolEnd;
#endif
};
_inline void STexPoolItemHdr::Unlink()
{
if (!m_Next || !m_Prev)
{
return;
}
m_Next->m_Prev = m_Prev;
m_Prev->m_Next = m_Next;
m_Next = m_Prev = NULL;
}
_inline void STexPoolItemHdr::Link(STexPoolItemHdr* pAfter)
{
if (m_Next || m_Prev)
{
return;
}
m_Next = pAfter->m_Next;
pAfter->m_Next->m_Prev = this;
pAfter->m_Next = this;
m_Prev = pAfter;
}
_inline void STexPoolItemHdr::UnlinkFree()
{
if (!m_NextFree || !m_PrevFree)
{
return;
}
m_NextFree->m_PrevFree = m_PrevFree;
m_PrevFree->m_NextFree = m_NextFree;
m_NextFree = m_PrevFree = NULL;
}
_inline void STexPoolItemHdr::LinkFree(STexPoolItemHdr* pAfter)
{
if (m_NextFree || m_PrevFree)
{
return;
}
m_NextFree = pAfter->m_NextFree;
pAfter->m_NextFree->m_PrevFree = this;
pAfter->m_NextFree = this;
m_PrevFree = pAfter;
}
#endif // CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_TEXTURES_TEXTURESTREAMPOOL_H