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;
auto Find = smShaderMap.find(mParametersHash);
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;
else mShaderStatus = eShaderExists;
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

View File

@ -161,4 +161,6 @@ void CEditorApplication::OnEditorClose()
mEditorWindows.removeOne(pEditor);
delete pEditor;
}
CGameProject::ActiveProject()->ResourceStore()->DestroyUnreferencedResources();
}

View File

@ -22,6 +22,7 @@ CProjectOverviewDialog::CProjectOverviewDialog(QWidget *pParent)
connect(mpUI->LaunchEditorButton, SIGNAL(clicked()), this, SLOT(LaunchEditor()));
connect(mpUI->ViewResourcesButton, SIGNAL(clicked()), this, SLOT(LaunchResourceBrowser()));
connect(mpUI->CookPackageButton, SIGNAL(clicked()), this, SLOT(CookPackage()));
connect(mpUI->CookAllDirtyPackagesButton, SIGNAL(clicked(bool)), this, SLOT(CookAllDirtyPackages()));
connect(gpEdApp, SIGNAL(AssetsModified()), this, SLOT(SetupPackagesList()));
}
@ -176,6 +177,7 @@ void CProjectOverviewDialog::LaunchEditor()
void CProjectOverviewDialog::LaunchResourceBrowser()
{
gpEdApp->ResourceBrowser()->show();
gpEdApp->ResourceBrowser()->raise();
}
void CProjectOverviewDialog::CookPackage()
@ -183,4 +185,11 @@ void CProjectOverviewDialog::CookPackage()
u32 PackageIdx = mpUI->PackagesList->currentRow();
CPackage *pPackage = mpProject->PackageByIndex(PackageIdx);
pPackage->Cook();
SetupPackagesList();
}
void CProjectOverviewDialog::CookAllDirtyPackages()
{
gpEdApp->CookAllDirtyPackages();
SetupPackagesList();
}

View File

@ -34,6 +34,7 @@ public slots:
void LaunchEditor();
void LaunchResourceBrowser();
void CookPackage();
void CookAllDirtyPackages();
void SetupWorldsList();
void SetupPackagesList();

View File

@ -125,6 +125,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="CookAllDirtyPackagesButton">
<property name="text">
<string>Cook All Dirty Packages</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -45,7 +45,6 @@ CCharacterEditor::CCharacterEditor(CAnimSet *pSet, QWidget *parent)
connect(ui->Viewport, SIGNAL(HoverBoneChanged(u32)), this, SLOT(OnViewportHoverBoneChanged(u32)));
connect(ui->Viewport, SIGNAL(ViewportClick(QMouseEvent*)), this, SLOT(OnViewportClick()));
connect(ui->ActionOpen, SIGNAL(triggered()), this, SLOT(Open()));
connect(ui->ActionShowGrid, SIGNAL(toggled(bool)), this, SLOT(ToggleGrid(bool)));
connect(ui->ActionShowMesh, SIGNAL(toggled(bool)), this, SLOT(ToggleMeshVisible(bool)));
connect(ui->ActionShowSkeleton, SIGNAL(toggled(bool)), this, SLOT(ToggleSkeletonVisible(bool)));
@ -230,26 +229,6 @@ CCharacterEditorViewport* CCharacterEditor::Viewport() const
}
// ************ PUBLIC SLOTS ************
void CCharacterEditor::Open()
{
QString CharFilename = QFileDialog::getOpenFileName(this, "Open Character", "", "Animation Character Set (*.ANCS)");
if (CharFilename.isEmpty()) return;
CAnimSet *pSet = (CAnimSet*) gpResourceStore->LoadResource(CharFilename.toStdString());
if (pSet)
{
SetActiveAnimSet(pSet);
}
else
{
QMessageBox::warning(this, "Error", "Couldn't load file: " + CharFilename);
}
gpResourceStore->DestroyUnreferencedResources();
}
void CCharacterEditor::ToggleGrid(bool Enable)
{
ui->Viewport->SetGridEnabled(Enable);

View File

@ -56,7 +56,6 @@ public:
CCharacterEditorViewport* Viewport() const;
public slots:
void Open();
void ToggleGrid(bool Enable);
void ToggleMeshVisible(bool Visible);
void ToggleSkeletonVisible(bool Visible);

View File

@ -49,7 +49,7 @@
<bool>false</bool>
</attribute>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="CCharacterEditorViewport" name="Viewport" native="true">
@ -312,12 +312,6 @@
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="MenuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="ActionOpen"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>Animation</string>
@ -336,7 +330,6 @@
<addaction name="ActionPrevAnim"/>
<addaction name="ActionNextAnim"/>
</widget>
<addaction name="MenuFile"/>
<addaction name="menuView"/>
</widget>
<widget class="QStatusBar" name="StatusBar"/>
@ -350,29 +343,12 @@
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="ActionOpen"/>
<addaction name="separator"/>
<addaction name="ActionShowGrid"/>
<addaction name="ActionShowMesh"/>
<addaction name="ActionShowSkeleton"/>
<addaction name="ActionBindPose"/>
<addaction name="ActionOrbit"/>
</widget>
<action name="ActionOpen">
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Open_24px.png</normaloff>:/icons/Open_24px.png</iconset>
</property>
<property name="text">
<string>Open</string>
</property>
<property name="toolTip">
<string>Open</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="ActionShowSkeleton">
<property name="checkable">
<bool>true</bool>

View File

@ -7,7 +7,6 @@
#include <Common/TString.h>
#include <Core/Render/CDrawUtil.h>
#include <Core/Render/CRenderer.h>
#include <Core/Resource/cooker/CModelCooker.h>
#include <Core/Resource/cooker/CTextureEncoder.h>
#include <Core/Resource/factory/CModelLoader.h>
#include <Core/Resource/factory/CMaterialLoader.h>
@ -47,9 +46,7 @@ CModelEditorWindow::CModelEditorWindow(CModel *pModel, QWidget *pParent)
// UI initialization
UpdateAnimParamUI(-1);
ui->IndTextureResSelector->SetAllowedExtensions("TXTR");
ui->IndTextureResSelector->SetPreviewPanelEnabled(true);
ui->PassTextureResSelector->SetAllowedExtensions("TXTR");
ui->PassTextureResSelector->SetPreviewPanelEnabled(true);
ui->PassTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
ui->PassTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
ui->ClearColorPicker->SetColor(QColor(76, 76, 76, 255));
@ -94,10 +91,8 @@ CModelEditorWindow::CModelEditorWindow(CModel *pModel, QWidget *pParent)
ui->AnimParamCSpinBox->setProperty ("ModelEditorWidgetType", eAnimParamCSpinBox);
ui->AnimParamDSpinBox->setProperty ("ModelEditorWidgetType", eAnimParamDSpinBox);
connect(ui->ActionOpen, SIGNAL(triggered()), this, SLOT(Open()));
connect(ui->ActionImport, SIGNAL(triggered()), this, SLOT(Import()));
connect(ui->ActionSave, SIGNAL(triggered()), this, SLOT(Save()));
connect(ui->ActionSaveAs, SIGNAL(triggered()), this, SLOT(SaveAs()));
connect(ui->ActionConvertToDDS, SIGNAL(triggered()), this, SLOT(ConvertToDDS()));
connect(ui->ActionConvertToTXTR, SIGNAL(triggered()), this, SLOT(ConvertToTXTR()));
connect(ui->MeshPreviewButton, SIGNAL(clicked()), this, SLOT(SetMeshPreview()));
@ -152,6 +147,7 @@ CModelEditorWindow::CModelEditorWindow(CModel *pModel, QWidget *pParent)
CModelEditorWindow::~CModelEditorWindow()
{
delete mpCurrentModelNode;
delete mpScene;
delete ui;
}
@ -236,9 +232,9 @@ void CModelEditorWindow::SetActiveMaterial(int MatIndex)
ui->DestBlendComboBox->setCurrentIndex(DstFac);
if (Settings & CMaterial::eIndStage)
ui->IndTextureResSelector->SetText(TO_QSTRING(mpCurrentMat->IndTexture()->FullSource()));
ui->IndTextureResSelector->SetResource(mpCurrentMat->IndTexture());
else
ui->IndTextureResSelector->SetText("");
ui->IndTextureResSelector->Clear();
for (u32 iKonst = 0; iKonst < 4; iKonst++)
{
@ -318,12 +314,7 @@ void CModelEditorWindow::SetActivePass(int PassIndex)
else TexCoordSrc++;
if (TexCoordSrc >= 5) TexCoordSrc -= 2;
CTexture *pPassTex = mpCurrentPass->Texture();
if (pPassTex)
ui->PassTextureResSelector->SetText(TO_QSTRING(pPassTex->FullSource()));
else
ui->PassTextureResSelector->SetText("");
ui->PassTextureResSelector->SetResource(mpCurrentPass->Texture());
ui->TevKColorSelComboBox->setCurrentIndex(KColor);
ui->TevKAlphaSelComboBox->setCurrentIndex(KAlpha);
ui->TevRasSelComboBox->setCurrentIndex(Ras);
@ -715,22 +706,6 @@ void CModelEditorWindow::UpdateAnimParamUI(int Mode)
}
}
void CModelEditorWindow::Open()
{
QString ModelFilename = QFileDialog::getOpenFileName(this, "Save model", "", "Retro Model (*.CMDL)");
if (ModelFilename.isEmpty()) return;
TResPtr<CModel> pModel = gpResourceStore->LoadResource(ModelFilename.toStdString());
if (pModel)
{
SetActiveModel(pModel);
SET_WINDOWTITLE_APPVARS("%APP_FULL_NAME% - Model Editor: " + TO_QSTRING(pModel->Source()));
mOutputFilename = TO_QSTRING(pModel->FullSource());
}
gpResourceStore->DestroyUnreferencedResources();
}
void CModelEditorWindow::Import()
{
QString FileName = QFileDialog::getOpenFileName(this, "Model", "", "*.obj;*.fbx;*.dae;*.3ds;*.blend");
@ -777,28 +752,10 @@ void CModelEditorWindow::Import()
void CModelEditorWindow::Save()
{
if (!mpCurrentModel) return;
bool SaveSuccess = mpCurrentModel->Entry()->Save();
if (mOutputFilename.isEmpty())
{
SaveAs();
return;
}
CFileOutStream CMDLOut(mOutputFilename.toStdString(), IOUtil::eBigEndian);
CModelCooker::CookCMDL(mpCurrentModel, CMDLOut);
QMessageBox::information(this, "Saved", "Model saved!");
}
void CModelEditorWindow::SaveAs()
{
QString FileName = QFileDialog::getSaveFileName(this, "Save model", "", "Retro Model (*.CMDL)");
if (FileName.isEmpty()) return;
mOutputFilename = FileName;
Save();
TString Name = TString(FileName.toStdString());
SET_WINDOWTITLE_APPVARS("%APP_FULL_NAME% - Model Editor: " + TO_QSTRING(Name));
if (SaveSuccess)
gpEdApp->NotifyAssetsModified();
}
void CModelEditorWindow::ConvertToDDS()

View File

@ -17,6 +17,7 @@ namespace Ui {
class CModelEditorWindow;
}
// the model editor is messy and old as fuck, it needs a total rewrite
class CModelEditorWindow : public IEditor
{
Q_OBJECT
@ -98,10 +99,8 @@ private:
};
private slots:
void Open();
void Import();
void Save();
void SaveAs();
void ConvertToDDS();
void ConvertToTXTR();
void SetMeshPreview();

View File

@ -172,7 +172,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-489</y>
<width>308</width>
<height>1184</height>
</rect>
@ -455,7 +455,7 @@
</widget>
</item>
<item>
<widget class="WResourceSelector" name="IndTextureResSelector" native="true">
<widget class="CResourceSelector" name="IndTextureResSelector" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
@ -1128,7 +1128,7 @@
</widget>
</item>
<item>
<widget class="WResourceSelector" name="PassTextureResSelector" native="true">
<widget class="CResourceSelector" name="PassTextureResSelector" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
@ -2399,7 +2399,6 @@
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
</widget>
<widget class="QMenuBar" name="menubar">
@ -2415,12 +2414,8 @@
<property name="title">
<string>File</string>
</property>
<addaction name="ActionOpen"/>
<addaction name="ActionSave"/>
<addaction name="ActionSaveAs"/>
<addaction name="ActionImport"/>
<addaction name="separator"/>
<addaction name="ActionExit"/>
</widget>
<widget class="QMenu" name="menuTextures">
<property name="title">
@ -2432,20 +2427,11 @@
<addaction name="menuFile"/>
<addaction name="menuTextures"/>
</widget>
<action name="ActionOpen">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="ActionExit">
<property name="text">
<string>Exit</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</action>
<action name="ActionSave">
<property name="icon">
<iconset resource="../Icons.qrc">
<normaloff>:/icons/Save.png</normaloff>:/icons/Save.png</iconset>
</property>
<property name="text">
<string>Save</string>
</property>
@ -2455,21 +2441,11 @@
<string>Export to DDS</string>
</property>
</action>
<action name="ActionExportCurrentModelTextures">
<property name="text">
<string>Export curent model's textures</string>
</property>
</action>
<action name="ActionImport">
<property name="text">
<string>Import</string>
</property>
</action>
<action name="ActionSaveAs">
<property name="text">
<string>Save as...</string>
</property>
</action>
<action name="ActionConvertToTXTR">
<property name="text">
<string>Convert DDS to TXTR</string>
@ -2491,18 +2467,18 @@
<signal>ColorChanged(QColor)</signal>
</slots>
</customwidget>
<customwidget>
<class>WResourceSelector</class>
<extends>QWidget</extends>
<header>Editor/Widgets/WResourceSelector.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CModelEditorViewport</class>
<extends>QWidget</extends>
<header>Editor/ModelEditor/CModelEditorViewport.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CResourceSelector</class>
<extends>QWidget</extends>
<header>Editor/Widgets/CResourceSelector.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../Icons.qrc"/>