refactor: add shader pass and backend variants
This commit is contained in:
@@ -22,6 +22,13 @@ enum class ShaderLanguage : Core::uint8 {
|
||||
SPIRV
|
||||
};
|
||||
|
||||
enum class ShaderBackend : Core::uint8 {
|
||||
Generic = 0,
|
||||
D3D12,
|
||||
OpenGL,
|
||||
Vulkan
|
||||
};
|
||||
|
||||
struct ShaderUniform {
|
||||
Containers::String name;
|
||||
Core::uint32 location;
|
||||
@@ -36,6 +43,27 @@ struct ShaderAttribute {
|
||||
Core::uint32 type;
|
||||
};
|
||||
|
||||
struct ShaderPassTagEntry {
|
||||
Containers::String name;
|
||||
Containers::String value;
|
||||
};
|
||||
|
||||
struct ShaderStageVariant {
|
||||
ShaderType stage = ShaderType::Fragment;
|
||||
ShaderLanguage language = ShaderLanguage::GLSL;
|
||||
ShaderBackend backend = ShaderBackend::Generic;
|
||||
Containers::String entryPoint;
|
||||
Containers::String profile;
|
||||
Containers::String sourceCode;
|
||||
Containers::Array<Core::uint8> compiledBinary;
|
||||
};
|
||||
|
||||
struct ShaderPass {
|
||||
Containers::String name;
|
||||
Containers::Array<ShaderPassTagEntry> tags;
|
||||
Containers::Array<ShaderStageVariant> variants;
|
||||
};
|
||||
|
||||
class Shader : public IResource {
|
||||
public:
|
||||
Shader();
|
||||
@@ -49,10 +77,10 @@ public:
|
||||
size_t GetMemorySize() const override { return m_memorySize; }
|
||||
void Release() override;
|
||||
|
||||
void SetShaderType(ShaderType type) { m_shaderType = type; }
|
||||
void SetShaderType(ShaderType type);
|
||||
ShaderType GetShaderType() const { return m_shaderType; }
|
||||
|
||||
void SetShaderLanguage(ShaderLanguage lang) { m_language = lang; }
|
||||
void SetShaderLanguage(ShaderLanguage lang);
|
||||
ShaderLanguage GetShaderLanguage() const { return m_language; }
|
||||
|
||||
void SetSourceCode(const Containers::String& source);
|
||||
@@ -66,11 +94,33 @@ public:
|
||||
|
||||
void AddAttribute(const ShaderAttribute& attribute);
|
||||
const Containers::Array<ShaderAttribute>& GetAttributes() const { return m_attributes; }
|
||||
|
||||
void AddPass(const ShaderPass& pass);
|
||||
void ClearPasses();
|
||||
Core::uint32 GetPassCount() const { return static_cast<Core::uint32>(m_passes.Size()); }
|
||||
const Containers::Array<ShaderPass>& GetPasses() const { return m_passes; }
|
||||
|
||||
void AddPassVariant(const Containers::String& passName, const ShaderStageVariant& variant);
|
||||
void SetPassTag(
|
||||
const Containers::String& passName,
|
||||
const Containers::String& tagName,
|
||||
const Containers::String& tagValue);
|
||||
bool HasPass(const Containers::String& passName) const;
|
||||
const ShaderPass* FindPass(const Containers::String& passName) const;
|
||||
ShaderPass* FindPass(const Containers::String& passName);
|
||||
const ShaderStageVariant* FindVariant(
|
||||
const Containers::String& passName,
|
||||
ShaderType stage,
|
||||
ShaderBackend backend = ShaderBackend::Generic) const;
|
||||
|
||||
class IRHIShader* GetRHIResource() const { return m_rhiResource; }
|
||||
void SetRHIResource(class IRHIShader* resource);
|
||||
|
||||
private:
|
||||
ShaderPass& GetOrCreatePass(const Containers::String& passName);
|
||||
ShaderStageVariant& GetOrCreateLegacyVariant();
|
||||
void SyncLegacyVariant();
|
||||
|
||||
ShaderType m_shaderType = ShaderType::Fragment;
|
||||
ShaderLanguage m_language = ShaderLanguage::GLSL;
|
||||
|
||||
@@ -79,6 +129,7 @@ private:
|
||||
|
||||
Containers::Array<ShaderUniform> m_uniforms;
|
||||
Containers::Array<ShaderAttribute> m_attributes;
|
||||
Containers::Array<ShaderPass> m_passes;
|
||||
|
||||
class IRHIShader* m_rhiResource = nullptr;
|
||||
};
|
||||
|
||||
@@ -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