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