Added shader sharing mechanism; added "cook all dirty packages" button; other various tweaks and fixes

This commit is contained in:
Aruki
2017-02-09 10:54:38 -07:00
parent 9b6376af68
commit 6d77604667
19 changed files with 139 additions and 145 deletions

View File

@@ -11,6 +11,7 @@
u64 CMaterial::sCurrentMaterial = 0;
CColor CMaterial::sCurrentTint = CColor::skWhite;
std::map<u64, CMaterial::SMaterialShader> CMaterial::smShaderMap;
CMaterial::CMaterial()
: mpShader(nullptr)
@@ -64,7 +65,7 @@ CMaterial::~CMaterial()
for (u32 iPass = 0; iPass < mPasses.size(); iPass++)
delete mPasses[iPass];
delete mpShader;
ClearShader();
}
CMaterial* CMaterial::Clone()
@@ -93,13 +94,65 @@ CMaterial* CMaterial::Clone()
void CMaterial::GenerateShader(bool AllowRegen /*= true*/)
{
HashParameters(); // Calling HashParameters() may change mShaderStatus so call it before checking
if (mShaderStatus != eShaderExists || AllowRegen)
{
delete mpShader;
mpShader = CShaderGenerator::GenerateShader(*this);
auto Find = smShaderMap.find(mParametersHash);
if (!mpShader->IsValidProgram()) mShaderStatus = eShaderFailed;
else mShaderStatus = eShaderExists;
if (Find != smShaderMap.end())
{
SMaterialShader& rShader = Find->second;
if (rShader.pShader == mpShader)
return;
ClearShader();
mpShader = rShader.pShader;
rShader.NumReferences++;
}
else
{
ClearShader();
mpShader = CShaderGenerator::GenerateShader(*this);
if (!mpShader->IsValidProgram())
{
mShaderStatus = eShaderFailed;
delete mpShader;
mpShader = nullptr;
}
else
{
mShaderStatus = eShaderExists;
smShaderMap[mParametersHash] = SMaterialShader { 1, mpShader };
}
}
}
}
void CMaterial::ClearShader()
{
if (mpShader)
{
auto Find = smShaderMap.find(mParametersHash);
ASSERT(Find != smShaderMap.end());
SMaterialShader& rShader = Find->second;
ASSERT(rShader.pShader == mpShader);
rShader.NumReferences--;
if (rShader.NumReferences == 0)
{
delete mpShader;
smShaderMap.erase(Find);
}
mpShader = nullptr;
mShaderStatus = eNoShader;
}
}
@@ -206,7 +259,12 @@ u64 CMaterial::HashParameters()
for (u32 iPass = 0; iPass < mPasses.size(); iPass++)
mPasses[iPass]->HashParameters(Hash);
mParametersHash = Hash.GetHash64();
u64 NewHash = Hash.GetHash64();
if (mParametersHash != NewHash)
ClearShader();
mParametersHash = NewHash;
mRecalcHash = false;
}

View File

@@ -72,6 +72,14 @@ private:
std::vector<CMaterialPass*> mPasses;
// Reuse shaders between materials that have identical TEV setups
struct SMaterialShader
{
int NumReferences;
CShader *pShader;
};
static std::map<u64, SMaterialShader> smShaderMap;
public:
CMaterial();
CMaterial(EGame Version, FVertexDescription VtxDesc);
@@ -79,6 +87,7 @@ public:
CMaterial* Clone();
void GenerateShader(bool AllowRegen = true);
void ClearShader();
bool SetCurrent(FRenderOptions Options);
u64 HashParameters();
void Update();