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

@@ -49,7 +49,7 @@ void CPackage::Cook()
CPackageDependencyListBuilder Builder(this);
std::list<CAssetID> AssetList;
Builder.BuildDependencyList(true, AssetList);
Log::Write(TString::FromInt32(AssetList.size(), 0, 10) + " assets in pak");
Log::Write(TString::FromInt32(AssetList.size(), 0, 10) + " assets in " + Name() + ".pak");
// Get named resources
std::list<const SNamedResource*> NamedResources;
@@ -207,6 +207,9 @@ void CPackage::Cook()
mNeedsRecook = false;
Save();
Log::Write("Finished writing " + PakPath.ToUTF8());
// Update resource store in case we recooked any assets
mpProject->ResourceStore()->ConditionalSaveStore();
}
void CPackage::CompareOriginalAssetList(const std::list<CAssetID>& rkNewList)

View File

@@ -214,6 +214,8 @@ bool CResourceEntry::Save(bool SkipCacheSave /*= false*/)
}
// Resource has been saved; now make sure dependencies, cache data, and packages are all up to date
mFlags |= eREF_HasBeenModified;
UpdateDependencies();
mpStore->SetCacheDataDirty();
@@ -257,7 +259,11 @@ bool CResourceEntry::Cook()
bool Success = CResourceCooker::CookResource(this, File);
if (Success)
mFlags.ClearFlag(eREF_NeedsRecook);
{
mFlags &= ~eREF_NeedsRecook;
mFlags |= eREF_HasBeenModified;
mpStore->SetCacheDataDirty();
}
return Success;
}
@@ -281,6 +287,7 @@ CResource* CResourceEntry::Load()
CXMLReader Reader(RawAssetPath());
mpResource->Serialize(Reader);
mpStore->TrackLoadedResource(this);
gpResourceStore = pOldStore;
}

View File

@@ -19,8 +19,9 @@ enum EResEntryFlag
eREF_Transient = 0x00000002, // Resource is transient (not part of a game project resource DB)
eREF_Hidden = 0x00000004, // Resource is hidden, doesn't show up in resource browser
eREF_HasBeenModified = 0x00000008, // Resource has been modified and resaved by the user
eREF_IsUserResource = 0x00000010, // Resource was created by the user (i.e. isn't a Retro Studios asset)
// Flags that save to the cache file
eREF_SavedFlags = eREF_NeedsRecook | eREF_Hidden | eREF_HasBeenModified
eREF_SavedFlags = eREF_NeedsRecook | eREF_Hidden | eREF_HasBeenModified | eREF_IsUserResource
};
DECLARE_FLAGS(EResEntryFlag, FResEntryFlags)

View File

@@ -14,6 +14,7 @@ using namespace tinyxml2;
CResourceStore *gpResourceStore = nullptr;
CResourceStore *gpEditorStore = nullptr;
// Constructor for editor store
CResourceStore::CResourceStore(const TWideString& rkDatabasePath)
: mpProj(nullptr)
, mGame(eUnknownGame)
@@ -26,6 +27,7 @@ CResourceStore::CResourceStore(const TWideString& rkDatabasePath)
mDatabaseName = rkDatabasePath.GetFileName();
}
// Constructor for game exporter
CResourceStore::CResourceStore(CGameProject *pProject, CGameExporter *pExporter, const TWideString& rkRawDir, const TWideString& rkCookedDir, EGame Game)
: mpProj(nullptr)
, mGame(Game)
@@ -38,6 +40,7 @@ CResourceStore::CResourceStore(CGameProject *pProject, CGameExporter *pExporter,
SetProject(pProject);
}
// Main constructor for game projects
CResourceStore::CResourceStore(CGameProject *pProject)
: mpProj(nullptr)
, mGame(eUnknownGame)

View File

@@ -13,12 +13,14 @@ u64 gFailedCompileCount = 0;
u64 gSuccessfulCompileCount = 0;
CShader* CShader::spCurrentShader = nullptr;
int CShader::smNumShaders = 0;
CShader::CShader()
{
mVertexShaderExists = false;
mPixelShaderExists = false;
mProgramExists = false;
smNumShaders++;
}
CShader::CShader(const char *pkVertexSource, const char *pkPixelSource)
@@ -26,6 +28,7 @@ CShader::CShader(const char *pkVertexSource, const char *pkPixelSource)
mVertexShaderExists = false;
mPixelShaderExists = false;
mProgramExists = false;
smNumShaders++;
CompileVertexSource(pkVertexSource);
CompilePixelSource(pkPixelSource);
@@ -39,6 +42,7 @@ CShader::~CShader()
if (mProgramExists) glDeleteProgram(mProgram);
if (spCurrentShader == this) spCurrentShader = 0;
smNumShaders--;
}
bool CShader::CompileVertexSource(const char* pkSource)

View File

@@ -23,6 +23,7 @@ class CShader
GLint mTextureUniforms[8];
GLint mNumLightsUniform;
static int smNumShaders;
static CShader* spCurrentShader;
public:
@@ -45,6 +46,8 @@ public:
static CShader* CurrentShader();
static void KillCachedShader();
inline static int NumShaders() { return smNumShaders; }
private:
void CacheCommonUniforms();
void DumpShaderSource(GLuint Shader, const TString& rkOut);

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();

View File

@@ -26,6 +26,7 @@ CScene::CScene()
CScene::~CScene()
{
ClearScene();
delete mpSceneRootNode;
}
bool CScene::IsNodeIDUsed(u32 ID) const