refactor: add shader pass and backend variants
This commit is contained in:
@@ -3,25 +3,46 @@
|
||||
namespace XCEngine {
|
||||
namespace Resources {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* kLegacyShaderPassName = "Default";
|
||||
|
||||
} // namespace
|
||||
|
||||
Shader::Shader() = default;
|
||||
|
||||
Shader::~Shader() = default;
|
||||
|
||||
void Shader::Release() {
|
||||
m_shaderType = ShaderType::Fragment;
|
||||
m_language = ShaderLanguage::GLSL;
|
||||
m_sourceCode.Clear();
|
||||
m_compiledBinary.Clear();
|
||||
m_uniforms.Clear();
|
||||
m_attributes.Clear();
|
||||
m_passes.Clear();
|
||||
m_rhiResource = nullptr;
|
||||
m_isValid = false;
|
||||
}
|
||||
|
||||
void Shader::SetShaderType(ShaderType type) {
|
||||
m_shaderType = type;
|
||||
SyncLegacyVariant();
|
||||
}
|
||||
|
||||
void Shader::SetShaderLanguage(ShaderLanguage lang) {
|
||||
m_language = lang;
|
||||
SyncLegacyVariant();
|
||||
}
|
||||
|
||||
void Shader::SetSourceCode(const Containers::String& source) {
|
||||
m_sourceCode = source;
|
||||
SyncLegacyVariant();
|
||||
}
|
||||
|
||||
void Shader::SetCompiledBinary(const Containers::Array<Core::uint8>& binary) {
|
||||
m_compiledBinary = binary;
|
||||
SyncLegacyVariant();
|
||||
}
|
||||
|
||||
void Shader::AddUniform(const ShaderUniform& uniform) {
|
||||
@@ -32,9 +53,123 @@ void Shader::AddAttribute(const ShaderAttribute& attribute) {
|
||||
m_attributes.PushBack(attribute);
|
||||
}
|
||||
|
||||
void Shader::AddPass(const ShaderPass& pass) {
|
||||
m_passes.PushBack(pass);
|
||||
}
|
||||
|
||||
void Shader::ClearPasses() {
|
||||
m_passes.Clear();
|
||||
}
|
||||
|
||||
void Shader::AddPassVariant(
|
||||
const Containers::String& passName,
|
||||
const ShaderStageVariant& variant) {
|
||||
ShaderPass& pass = GetOrCreatePass(passName);
|
||||
pass.variants.PushBack(variant);
|
||||
}
|
||||
|
||||
void Shader::SetPassTag(
|
||||
const Containers::String& passName,
|
||||
const Containers::String& tagName,
|
||||
const Containers::String& tagValue) {
|
||||
ShaderPass& pass = GetOrCreatePass(passName);
|
||||
for (ShaderPassTagEntry& tag : pass.tags) {
|
||||
if (tag.name == tagName) {
|
||||
tag.value = tagValue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ShaderPassTagEntry& tag = pass.tags.EmplaceBack();
|
||||
tag.name = tagName;
|
||||
tag.value = tagValue;
|
||||
}
|
||||
|
||||
bool Shader::HasPass(const Containers::String& passName) const {
|
||||
return FindPass(passName) != nullptr;
|
||||
}
|
||||
|
||||
const ShaderPass* Shader::FindPass(const Containers::String& passName) const {
|
||||
for (const ShaderPass& pass : m_passes) {
|
||||
if (pass.name == passName) {
|
||||
return &pass;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ShaderPass* Shader::FindPass(const Containers::String& passName) {
|
||||
for (ShaderPass& pass : m_passes) {
|
||||
if (pass.name == passName) {
|
||||
return &pass;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ShaderStageVariant* Shader::FindVariant(
|
||||
const Containers::String& passName,
|
||||
ShaderType stage,
|
||||
ShaderBackend backend) const {
|
||||
const ShaderPass* pass = FindPass(passName);
|
||||
if (pass == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ShaderStageVariant* genericVariant = nullptr;
|
||||
for (const ShaderStageVariant& variant : pass->variants) {
|
||||
if (variant.stage != stage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (variant.backend == backend) {
|
||||
return &variant;
|
||||
}
|
||||
|
||||
if (variant.backend == ShaderBackend::Generic && genericVariant == nullptr) {
|
||||
genericVariant = &variant;
|
||||
}
|
||||
}
|
||||
|
||||
return genericVariant;
|
||||
}
|
||||
|
||||
void Shader::SetRHIResource(class IRHIShader* resource) {
|
||||
m_rhiResource = resource;
|
||||
}
|
||||
|
||||
ShaderPass& Shader::GetOrCreatePass(const Containers::String& passName) {
|
||||
if (ShaderPass* pass = FindPass(passName)) {
|
||||
return *pass;
|
||||
}
|
||||
|
||||
ShaderPass& pass = m_passes.EmplaceBack();
|
||||
pass.name = passName;
|
||||
return pass;
|
||||
}
|
||||
|
||||
ShaderStageVariant& Shader::GetOrCreateLegacyVariant() {
|
||||
ShaderPass& pass = GetOrCreatePass(kLegacyShaderPassName);
|
||||
for (ShaderStageVariant& variant : pass.variants) {
|
||||
if (variant.backend == ShaderBackend::Generic) {
|
||||
return variant;
|
||||
}
|
||||
}
|
||||
|
||||
ShaderStageVariant& variant = pass.variants.EmplaceBack();
|
||||
variant.backend = ShaderBackend::Generic;
|
||||
return variant;
|
||||
}
|
||||
|
||||
void Shader::SyncLegacyVariant() {
|
||||
ShaderStageVariant& variant = GetOrCreateLegacyVariant();
|
||||
variant.stage = m_shaderType;
|
||||
variant.language = m_language;
|
||||
variant.sourceCode = m_sourceCode;
|
||||
variant.compiledBinary = m_compiledBinary;
|
||||
}
|
||||
|
||||
} // namespace Resources
|
||||
} // namespace XCEngine
|
||||
|
||||
Reference in New Issue
Block a user