Added required flags to UberShaderPreprocessor

Former-commit-id: 1118fb08d1c0a7f6ebd18042f9a2044738bc4169
This commit is contained in:
Lynix 2014-08-05 09:43:19 +02:00
parent 149ef145a3
commit b413727a21
2 changed files with 37 additions and 11 deletions

View File

@ -23,8 +23,8 @@ class NAZARA_API NzUberShaderPreprocessor : public NzUberShader
NzUberShaderInstance* Get(const NzParameterList& parameters) const; NzUberShaderInstance* Get(const NzParameterList& parameters) const;
void SetShader(nzShaderStage stage, const NzString& source, const NzString& flags); void SetShader(nzShaderStage stage, const NzString& source, const NzString& shaderFlags, const NzString& requiredFlags = NzString());
bool SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& flags); bool SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags = NzString());
static bool IsSupported(); static bool IsSupported();
@ -33,6 +33,7 @@ class NAZARA_API NzUberShaderPreprocessor : public NzUberShader
{ {
mutable std::unordered_map<nzUInt32, NzShaderStage> cache; mutable std::unordered_map<nzUInt32, NzShaderStage> cache;
std::unordered_map<NzString, nzUInt32> flags; std::unordered_map<NzString, nzUInt32> flags;
nzUInt32 requiredFlags;
NzString source; NzString source;
bool present = false; bool present = false;
}; };

View File

@ -32,7 +32,8 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param
{ {
try try
{ {
NzErrorFlags errFlags(nzErrorFlag_Silent | nzErrorFlag_ThrowException); // Une exception sera lancée à la moindre erreur et celle-ci ne sera pas enregistrée dans le log (car traitée dans le bloc catch)
NzErrorFlags errFlags(nzErrorFlag_Silent | nzErrorFlag_ThrowException, true);
std::unique_ptr<NzShader> shader(new NzShader); std::unique_ptr<NzShader> shader(new NzShader);
shader->SetPersistent(false); shader->SetPersistent(false);
@ -42,7 +43,8 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param
{ {
const Shader& shaderStage = m_shaders[i]; const Shader& shaderStage = m_shaders[i];
if (shaderStage.present) // Le shader stage est-il activé dans cette version du shader ?
if (shaderStage.present && (flags & shaderStage.requiredFlags) == shaderStage.requiredFlags)
{ {
nzUInt32 stageFlags = 0; nzUInt32 stageFlags = 0;
for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it) for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it)
@ -73,7 +75,7 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param
for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it) for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it)
code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n'; code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n';
code << "\n#line 1\n"; code << "\n#line 1\n"; // Pour que les éventuelles erreurs du shader se réfèrent à la bonne ligne
code << shaderStage.source; code << shaderStage.source;
stage.SetSource(code); stage.SetSource(code);
@ -90,6 +92,7 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param
shader->Link(); shader->Link();
// On construit l'instant
auto pair = m_cache.emplace(flags, shader.get()); auto pair = m_cache.emplace(flags, shader.get());
shader.release(); shader.release();
@ -99,23 +102,23 @@ NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& param
{ {
NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled); NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled);
NazaraError("Failed to build uber shader instance: " + NzError::GetLastError()); NazaraError("Failed to build UberShader instance: " + NzError::GetLastError());
throw; throw;
} }
} }
else else
return &shaderIt->second; return &shaderIt->second;
} }
void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& source, const NzString& flagString) void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& source, const NzString& shaderFlags, const NzString& requiredFlags)
{ {
Shader& shader = m_shaders[stage]; Shader& shader = m_shaders[stage];
shader.present = true; shader.present = true;
shader.source = source; shader.source = source;
// On extrait les flags de la chaîne
std::vector<NzString> flags; std::vector<NzString> flags;
flagString.Split(flags, ' '); shaderFlags.Split(flags, ' ');
for (NzString& flag : flags) for (NzString& flag : flags)
{ {
@ -127,9 +130,31 @@ void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& so
if (it2 == shader.flags.end()) if (it2 == shader.flags.end())
shader.flags[flag] = 1U << shader.flags.size(); shader.flags[flag] = 1U << shader.flags.size();
} }
// On construit les flags requis pour l'activation du shader
shader.requiredFlags = 0;
flags.clear();
requiredFlags.Split(flags, ' ');
for (NzString& flag : flags)
{
nzUInt32 flagVal;
auto it = m_flags.find(flag);
if (it == m_flags.end())
{
flagVal = 1U << m_flags.size();
m_flags[flag] = flagVal;
}
else
flagVal = it->second;
shader.requiredFlags |= flagVal;
}
} }
bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& flags) bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags)
{ {
NzFile file(filePath); NzFile file(filePath);
if (!file.Open(NzFile::ReadOnly | NzFile::Text)) if (!file.Open(NzFile::ReadOnly | NzFile::Text))
@ -150,7 +175,7 @@ bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzSt
file.Close(); file.Close();
SetShader(stage, source, flags); SetShader(stage, source, shaderFlags, requiredFlags);
return true; return true;
} }