238 lines
7.2 KiB
C++
238 lines
7.2 KiB
C++
|
|
|
|
#include "trenderer.h"
|
|
#include "trasterfx.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "tpredictivecachemanager.h"
|
|
|
|
//************************************************************************************************
|
|
// Preliminaries
|
|
//************************************************************************************************
|
|
|
|
class TPredictiveCacheManagerGenerator : public TRenderResourceManagerGenerator
|
|
{
|
|
public:
|
|
TPredictiveCacheManagerGenerator() : TRenderResourceManagerGenerator(true) {}
|
|
|
|
TRenderResourceManager *operator()(void)
|
|
{
|
|
return new TPredictiveCacheManager;
|
|
}
|
|
};
|
|
|
|
MANAGER_FILESCOPE_DECLARATION_DEP(
|
|
TPredictiveCacheManager,
|
|
TPredictiveCacheManagerGenerator,
|
|
TFxCacheManager::deps())
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
TPredictiveCacheManager *TPredictiveCacheManager::instance()
|
|
{
|
|
return static_cast<TPredictiveCacheManager *>(
|
|
//TPredictiveCacheManager::gen()->getManager(TRenderer::instance())
|
|
TPredictiveCacheManager::gen()->getManager(TRenderer::renderId()));
|
|
}
|
|
|
|
//************************************************************************************************
|
|
// TPredictiveCacheManager::Imp definition
|
|
//************************************************************************************************
|
|
|
|
//=======================
|
|
// PredictionData
|
|
//-----------------------
|
|
|
|
struct PredictionData {
|
|
const ResourceDeclaration *m_decl;
|
|
int m_usageCount;
|
|
|
|
PredictionData(const ResourceDeclaration *declaration)
|
|
: m_decl(declaration), m_usageCount(1) {}
|
|
};
|
|
|
|
//============================================================================================
|
|
|
|
//=====================================
|
|
// TPredictiveCacheManager::Imp
|
|
//-------------------------------------
|
|
|
|
class TPredictiveCacheManager::Imp
|
|
{
|
|
public:
|
|
int m_renderStatus;
|
|
bool m_enabled;
|
|
|
|
std::map<TCacheResourceP, PredictionData> m_resources;
|
|
QMutex m_mutex;
|
|
|
|
public:
|
|
//Active getResource(..) callback
|
|
typedef void (TPredictiveCacheManager::Imp::*GetResourceFuncPtr)(TCacheResourceP &resource, const string &alias,
|
|
const TFxP &fx, double frame, const TRenderSettings &rs,
|
|
ResourceDeclaration *resData);
|
|
|
|
GetResourceFuncPtr m_getResFuncPtr;
|
|
|
|
public:
|
|
Imp()
|
|
: m_renderStatus(TRenderer::IDLE), m_getResFuncPtr(&Imp::getResourceComputing), m_enabled(TRenderer::instance().isPrecomputingEnabled()) {}
|
|
|
|
void getResourceTestRun(
|
|
TCacheResourceP &resource, const string &alias,
|
|
const TFxP &fx, double frame, const TRenderSettings &rs,
|
|
ResourceDeclaration *resData);
|
|
|
|
void getResourceComputing(
|
|
TCacheResourceP &resource, const string &alias,
|
|
const TFxP &fx, double frame, const TRenderSettings &rs,
|
|
ResourceDeclaration *resData);
|
|
};
|
|
|
|
//************************************************************************************************
|
|
// TPredictiveCacheManager methods
|
|
//************************************************************************************************
|
|
|
|
TPredictiveCacheManager::TPredictiveCacheManager()
|
|
: m_imp(new TPredictiveCacheManager::Imp())
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
TPredictiveCacheManager::~TPredictiveCacheManager()
|
|
{
|
|
delete m_imp;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void TPredictiveCacheManager::setMaxTileSize(int maxTileSize)
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void TPredictiveCacheManager::setBPP(int bpp)
|
|
{
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void TPredictiveCacheManager::getResource(
|
|
TCacheResourceP &resource, const string &alias,
|
|
const TFxP &fx, double frame, const TRenderSettings &rs,
|
|
ResourceDeclaration *resData)
|
|
{
|
|
if (!m_imp->m_enabled)
|
|
return;
|
|
|
|
(m_imp->*(m_imp->m_getResFuncPtr))(resource, alias, fx, frame, rs, resData);
|
|
}
|
|
|
|
//************************************************************************************************
|
|
// Notification-related functions
|
|
//************************************************************************************************
|
|
|
|
void TPredictiveCacheManager::Imp::getResourceTestRun(
|
|
TCacheResourceP &resource, const string &alias,
|
|
const TFxP &fx, double frame, const TRenderSettings &rs,
|
|
ResourceDeclaration *resData)
|
|
{
|
|
assert(resData && resData->m_rawData);
|
|
if (!(resData && resData->m_rawData))
|
|
//This is a very rare case. I've seen it happen once in a 'pathologic' case
|
|
//which involved affines truncation while building aliases.
|
|
//The rendering system didn't expect the truncated part 'resurface' in a
|
|
//downstream fx with a slightly different affine alias.
|
|
|
|
//TODO: Affines should be coded completely in the aliases... in a compact way though.
|
|
return;
|
|
|
|
if (!resource)
|
|
resource = TCacheResourceP(alias, true);
|
|
|
|
//Lock against concurrent threads
|
|
//QMutexLocker locker(&m_mutex); //preComputing is currently single-threaded
|
|
|
|
std::map<TCacheResourceP, PredictionData>::iterator it =
|
|
m_resources.find(resource);
|
|
|
|
if (it != m_resources.end())
|
|
it->second.m_usageCount++;
|
|
else {
|
|
//Already initializes usageCount at 1
|
|
m_resources.insert(std::make_pair(resource, PredictionData(resData))).first;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void TPredictiveCacheManager::Imp::getResourceComputing(
|
|
TCacheResourceP &resource, const string &alias,
|
|
const TFxP &fx, double frame, const TRenderSettings &rs,
|
|
ResourceDeclaration *resData)
|
|
{
|
|
//If there is no declaration data, either the request can be resolved in one
|
|
//computation code (therefore it is uninteresting for us), or it was never declared.
|
|
//Anyway, return.
|
|
if (!resData)
|
|
return;
|
|
|
|
//NO! The refCount is dynamically depleted - could become 0 from n...
|
|
//assert(!(resData->m_tiles.size() == 1 && resData->m_tiles[0].m_refCount == 1));
|
|
|
|
if (!resource)
|
|
resource = TCacheResourceP(alias);
|
|
|
|
if (!resource)
|
|
return;
|
|
|
|
//Lock against concurrent threads
|
|
QMutexLocker locker(&m_mutex);
|
|
|
|
std::map<TCacheResourceP, PredictionData>::iterator it =
|
|
m_resources.find(resource);
|
|
|
|
if (it == m_resources.end())
|
|
return;
|
|
|
|
if (--it->second.m_usageCount <= 0)
|
|
m_resources.erase(it);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void TPredictiveCacheManager::onRenderStatusStart(int renderStatus)
|
|
{
|
|
m_imp->m_renderStatus = renderStatus;
|
|
switch (renderStatus) {
|
|
case TRenderer::TESTRUN:
|
|
m_imp->m_getResFuncPtr = &TPredictiveCacheManager::Imp::getResourceTestRun;
|
|
CASE TRenderer::COMPUTING : m_imp->m_getResFuncPtr = &TPredictiveCacheManager::Imp::getResourceComputing;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void TPredictiveCacheManager::onRenderStatusEnd(int renderStatus)
|
|
{
|
|
switch (renderStatus) {
|
|
case TRenderer::TESTRUN:
|
|
|
|
//All resources which have just 1 computation tile, which is also referenced
|
|
//only once, are released.
|
|
|
|
std::map<TCacheResourceP, PredictionData>::iterator it;
|
|
for (it = m_imp->m_resources.begin(); it != m_imp->m_resources.end();) {
|
|
const ResourceDeclaration *decl = it->second.m_decl;
|
|
|
|
if (decl->m_tiles.size() == 1 && decl->m_tiles[0].m_refCount == 1) {
|
|
std::map<TCacheResourceP, PredictionData>::iterator jt = it++;
|
|
m_imp->m_resources.erase(jt);
|
|
} else
|
|
it++;
|
|
}
|
|
}
|
|
}
|