mirror of https://github.com/AxioDL/metaforce.git
Support for per-stage shader hashing
This commit is contained in:
parent
82fc24ebe6
commit
7cc157c8b9
|
@ -12,6 +12,7 @@ class FileStoreManager;
|
||||||
extern CVar* com_developer;
|
extern CVar* com_developer;
|
||||||
extern CVar* com_configfile;
|
extern CVar* com_configfile;
|
||||||
extern CVar* com_enableCheats;
|
extern CVar* com_enableCheats;
|
||||||
|
extern CVar* com_cubemaps;
|
||||||
class CVarManager final {
|
class CVarManager final {
|
||||||
using CVarContainer = DNACVAR::CVarContainer;
|
using CVarContainer = DNACVAR::CVarContainer;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -295,8 +295,8 @@ public:
|
||||||
|
|
||||||
template <class FromTp>
|
template <class FromTp>
|
||||||
StageTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
|
StageTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
|
||||||
if (FromTp::HasHash) {
|
if constexpr (FromTp::HasStageHash) {
|
||||||
uint64_t hash = in.Hash();
|
uint64_t hash = in.template StageHash<S>();
|
||||||
auto search = m_stageCache.find(hash);
|
auto search = m_stageCache.find(hash);
|
||||||
if (search != m_stageCache.end())
|
if (search != m_stageCache.end())
|
||||||
return search->second;
|
return search->second;
|
||||||
|
@ -406,7 +406,7 @@ public:
|
||||||
|
|
||||||
template <class FromTp>
|
template <class FromTp>
|
||||||
PipelineTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
|
PipelineTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
|
||||||
if (FromTp::HasHash) {
|
if constexpr (FromTp::HasHash) {
|
||||||
uint64_t hash = in.Hash();
|
uint64_t hash = in.Hash();
|
||||||
auto search = m_pipelineCache.find(hash);
|
auto search = m_pipelineCache.find(hash);
|
||||||
if (search != m_pipelineCache.end())
|
if (search != m_pipelineCache.end())
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace hecl {
|
||||||
CVar* com_developer = nullptr;
|
CVar* com_developer = nullptr;
|
||||||
CVar* com_configfile = nullptr;
|
CVar* com_configfile = nullptr;
|
||||||
CVar* com_enableCheats = nullptr;
|
CVar* com_enableCheats = nullptr;
|
||||||
|
CVar* com_cubemaps = nullptr;
|
||||||
|
|
||||||
static const std::regex cmdLineRegex("\\+([\\w\\.]+)=([\\w\\.\\-]+)");
|
static const std::regex cmdLineRegex("\\+([\\w\\.]+)=([\\w\\.\\-]+)");
|
||||||
CVarManager* CVarManager::m_instance = nullptr;
|
CVarManager* CVarManager::m_instance = nullptr;
|
||||||
|
@ -26,6 +27,9 @@ CVarManager::CVarManager(hecl::Runtime::FileStoreManager& store, bool useBinary)
|
||||||
com_enableCheats =
|
com_enableCheats =
|
||||||
newCVar("cheats", "Enable cheats", false,
|
newCVar("cheats", "Enable cheats", false,
|
||||||
(CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::Hidden | CVar::EFlags::InternalArchivable));
|
(CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::Hidden | CVar::EFlags::InternalArchivable));
|
||||||
|
com_cubemaps =
|
||||||
|
newCVar("cubemaps", "Enable cubemaps", false,
|
||||||
|
(CVar::EFlags::Game | CVar::EFlags::ReadOnly | CVar::EFlags::InternalArchivable));
|
||||||
}
|
}
|
||||||
|
|
||||||
CVarManager::~CVarManager() {}
|
CVarManager::~CVarManager() {}
|
||||||
|
|
|
@ -31,6 +31,14 @@ Format(const char* format, ...) {
|
||||||
return std::string(resultBuf, printSz);
|
return std::string(resultBuf, printSz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* StageNames[] = {
|
||||||
|
"hecl::PipelineStage::Vertex",
|
||||||
|
"hecl::PipelineStage::Fragment",
|
||||||
|
"hecl::PipelineStage::Geometry",
|
||||||
|
"hecl::PipelineStage::Control",
|
||||||
|
"hecl::PipelineStage::Evaluation"
|
||||||
|
};
|
||||||
|
|
||||||
const std::string* Compiler::getFileContents(SystemStringView path) {
|
const std::string* Compiler::getFileContents(SystemStringView path) {
|
||||||
auto search = m_fileContents.find(path.data());
|
auto search = m_fileContents.find(path.data());
|
||||||
if (search == m_fileContents.end()) {
|
if (search == m_fileContents.end()) {
|
||||||
|
@ -59,6 +67,9 @@ static const char* ShaderHeaderTemplate =
|
||||||
" static const boo::AdditionalPipelineInfo PipelineInfo;\n"
|
" static const boo::AdditionalPipelineInfo PipelineInfo;\n"
|
||||||
" static constexpr bool HasHash = true;\n"
|
" static constexpr bool HasHash = true;\n"
|
||||||
" static constexpr uint64_t Hash() { return 0x%016llX; }\n"
|
" static constexpr uint64_t Hash() { return 0x%016llX; }\n"
|
||||||
|
" static constexpr bool HasStageHash = true;\n"
|
||||||
|
" template <typename S>\n"
|
||||||
|
" static constexpr uint64_t StageHash();\n"
|
||||||
"};\n\n";
|
"};\n\n";
|
||||||
|
|
||||||
static const char* StageObjectHeaderTemplate =
|
static const char* StageObjectHeaderTemplate =
|
||||||
|
@ -445,7 +456,12 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
|
||||||
StageType stageType;
|
StageType stageType;
|
||||||
auto stageBegin = includesPass.cend();
|
auto stageBegin = includesPass.cend();
|
||||||
auto stageEnd = includesPass.cend();
|
auto stageEnd = includesPass.cend();
|
||||||
std::unordered_map<std::string, std::pair<std::bitset<6>, std::set<std::string>>> shaderStageUses;
|
struct ShaderStageUse {
|
||||||
|
std::bitset<6> stages;
|
||||||
|
std::array<unsigned long long, 6> stageHashes = {};
|
||||||
|
std::set<std::string> platforms;
|
||||||
|
};
|
||||||
|
std::unordered_map<std::string, ShaderStageUse> shaderStageUses;
|
||||||
std::unordered_map<std::string, std::string> shaderBases;
|
std::unordered_map<std::string, std::string> shaderBases;
|
||||||
|
|
||||||
auto _DoCompile = [&]() {
|
auto _DoCompile = [&]() {
|
||||||
|
@ -465,9 +481,10 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stageBegin = includesPass.end();
|
stageBegin = includesPass.end();
|
||||||
std::pair<std::bitset<6>, std::set<std::string>>& uses = shaderStageUses[shaderName];
|
ShaderStageUse& uses = shaderStageUses[shaderName];
|
||||||
uses.first.set(size_t(stageType));
|
uses.stages.set(size_t(stageType));
|
||||||
uses.second.insert(stagePlatforms);
|
uses.stageHashes[size_t(stageType)] = XXH64(stage.c_str(), stage.size(), 0);
|
||||||
|
uses.platforms.insert(stagePlatforms);
|
||||||
return StageAction<CompileStageAction>(stagePlatforms, stageType, shaderName, shaderBase, stage, out.second);
|
return StageAction<CompileStageAction>(stagePlatforms, stageType, shaderName, shaderBase, stage, out.second);
|
||||||
};
|
};
|
||||||
auto DoCompile = [&](std::string platform, StageType type, std::string::const_iterator end,
|
auto DoCompile = [&](std::string platform, StageType type, std::string::const_iterator end,
|
||||||
|
@ -482,8 +499,8 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
|
||||||
auto DoShader = [&]() {
|
auto DoShader = [&]() {
|
||||||
if (shaderBase.empty() && shaderStageUses.find(shaderName) == shaderStageUses.cend())
|
if (shaderBase.empty() && shaderStageUses.find(shaderName) == shaderStageUses.cend())
|
||||||
return true;
|
return true;
|
||||||
std::pair<std::bitset<6>, std::set<std::string>>& uses = shaderStageUses[shaderName];
|
ShaderStageUse& uses = shaderStageUses[shaderName];
|
||||||
if (uses.first.test(5))
|
if (uses.stages.test(5))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
out.first += Format(ShaderHeaderTemplate, shaderName.c_str(), XXH64(shaderName.c_str(), shaderName.size(), 0));
|
out.first += Format(ShaderHeaderTemplate, shaderName.c_str(), XXH64(shaderName.c_str(), shaderName.size(), 0));
|
||||||
|
@ -494,22 +511,23 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
|
||||||
shaderBases[shaderName] = shaderBase;
|
shaderBases[shaderName] = shaderBase;
|
||||||
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
for (int i = 0; i < 5; ++i) {
|
||||||
if (uses.first.test(size_t(i)))
|
if (uses.stages.test(size_t(i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::string useBase = shaderBase;
|
std::string useBase = shaderBase;
|
||||||
std::unordered_map<std::string, std::pair<std::bitset<6>, std::set<std::string>>>::const_iterator baseUses =
|
std::unordered_map<std::string, ShaderStageUse>::const_iterator baseUses =
|
||||||
shaderStageUses.find(useBase);
|
shaderStageUses.find(useBase);
|
||||||
while (baseUses == shaderStageUses.cend() || !baseUses->second.first.test(size_t(i))) {
|
while (baseUses == shaderStageUses.cend() || !baseUses->second.stages.test(size_t(i))) {
|
||||||
auto search = shaderBases.find(useBase);
|
auto search = shaderBases.find(useBase);
|
||||||
if (search == shaderBases.cend())
|
if (search == shaderBases.cend())
|
||||||
break;
|
break;
|
||||||
useBase = search->second;
|
useBase = search->second;
|
||||||
baseUses = shaderStageUses.find(useBase);
|
baseUses = shaderStageUses.find(useBase);
|
||||||
}
|
}
|
||||||
if (baseUses == shaderStageUses.cend() || !baseUses->second.first.test(size_t(i)))
|
if (baseUses == shaderStageUses.cend() || !baseUses->second.stages.test(size_t(i)))
|
||||||
continue;
|
continue;
|
||||||
for (const std::string& basePlatforms : baseUses->second.second) {
|
for (const std::string& basePlatforms : baseUses->second.platforms) {
|
||||||
|
uses.stageHashes[size_t(i)] = baseUses->second.stageHashes[size_t(i)];
|
||||||
StageAction<CompileSubStageAction>(basePlatforms, StageType(i), shaderName, useBase, {}, out.second);
|
StageAction<CompileSubStageAction>(basePlatforms, StageType(i), shaderName, useBase, {}, out.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -587,7 +605,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
|
||||||
out.second += ", ";
|
out.second += ", ";
|
||||||
out.second += "};\n\n";
|
out.second += "};\n\n";
|
||||||
|
|
||||||
uses.first.set(5);
|
uses.stages.set(5);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -751,6 +769,17 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
|
||||||
if (!_DoCompile() || !DoShader())
|
if (!_DoCompile() || !DoShader())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
for (const auto& shader : shaderStageUses) {
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
if (shader.second.stageHashes[i]) {
|
||||||
|
out.first += "template <> constexpr uint64_t Shader_";
|
||||||
|
out.first += shader.first;
|
||||||
|
out.first += Format("::StageHash<%s>() { return 0x%016llX; }\n", StageNames[i], shader.second.stageHashes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.first += "\n";
|
||||||
|
|
||||||
out.first += "#define UNIVERSAL_PIPELINES_";
|
out.first += "#define UNIVERSAL_PIPELINES_";
|
||||||
out.first += baseName;
|
out.first += baseName;
|
||||||
for (const auto& shader : shaderStageUses) {
|
for (const auto& shader : shaderStageUses) {
|
||||||
|
|
Loading…
Reference in New Issue