feat: add unity-aligned shader contract metadata

This commit is contained in:
2026-04-03 00:01:31 +08:00
parent b43d4048b8
commit 6636834b35
9 changed files with 484 additions and 0 deletions

View File

@@ -122,11 +122,36 @@ struct BuiltinForwardMaterialData {
Math::Vector4 baseColorFactor = Math::Vector4::One();
};
inline const Resources::ShaderPropertyDesc* FindShaderPropertyBySemantic(
const Resources::Material* material,
const Containers::String& semantic) {
if (material == nullptr || material->GetShader() == nullptr) {
return nullptr;
}
const Containers::String normalizedSemantic = NormalizeBuiltinPassMetadataValue(semantic);
for (const Resources::ShaderPropertyDesc& property : material->GetShader()->GetProperties()) {
if (NormalizeBuiltinPassMetadataValue(property.semantic) == normalizedSemantic) {
return &property;
}
}
return nullptr;
}
inline Math::Vector4 ResolveBuiltinBaseColorFactor(const Resources::Material* material) {
if (material == nullptr) {
return Math::Vector4::One();
}
if (const Resources::ShaderPropertyDesc* property = FindShaderPropertyBySemantic(material, "BaseColor")) {
if (material->HasProperty(property->name) &&
(property->type == Resources::ShaderPropertyType::Color ||
property->type == Resources::ShaderPropertyType::Vector)) {
return material->GetFloat4(property->name);
}
}
static const char* kBaseColorPropertyNames[] = {
"baseColor",
"_BaseColor",
@@ -162,6 +187,13 @@ inline const Resources::Texture* ResolveBuiltinBaseColorTexture(const Resources:
return nullptr;
}
if (const Resources::ShaderPropertyDesc* property = FindShaderPropertyBySemantic(material, "BaseColorTexture")) {
const Resources::ResourceHandle<Resources::Texture> textureHandle = material->GetTexture(property->name);
if (textureHandle.Get() != nullptr && textureHandle->IsValid()) {
return textureHandle.Get();
}
}
static const char* kTextureNames[] = {
"baseColorTexture",
"_BaseColorTexture",

View File

@@ -29,6 +29,25 @@ enum class ShaderBackend : Core::uint8 {
Vulkan
};
// Keep shader property kinds close to Unity's public shader syntax so the
// runtime contract can be reused when ShaderLab-compatible parsing is added.
enum class ShaderPropertyType : Core::uint8 {
Float = 0,
Range,
Int,
Vector,
Color,
Texture2D,
TextureCube
};
enum class ShaderResourceType : Core::uint8 {
ConstantBuffer = 0,
Texture2D,
TextureCube,
Sampler
};
struct ShaderUniform {
Containers::String name;
Core::uint32 location;
@@ -48,6 +67,22 @@ struct ShaderPassTagEntry {
Containers::String value;
};
struct ShaderPropertyDesc {
Containers::String name;
Containers::String displayName;
ShaderPropertyType type = ShaderPropertyType::Float;
Containers::String defaultValue;
Containers::String semantic;
};
struct ShaderResourceBindingDesc {
Containers::String name;
ShaderResourceType type = ShaderResourceType::ConstantBuffer;
Core::uint32 set = 0;
Core::uint32 binding = 0;
Containers::String semantic;
};
struct ShaderStageVariant {
ShaderType stage = ShaderType::Fragment;
ShaderLanguage language = ShaderLanguage::GLSL;
@@ -61,6 +96,7 @@ struct ShaderStageVariant {
struct ShaderPass {
Containers::String name;
Containers::Array<ShaderPassTagEntry> tags;
Containers::Array<ShaderResourceBindingDesc> resources;
Containers::Array<ShaderStageVariant> variants;
};
@@ -95,6 +131,11 @@ public:
void AddAttribute(const ShaderAttribute& attribute);
const Containers::Array<ShaderAttribute>& GetAttributes() const { return m_attributes; }
void AddProperty(const ShaderPropertyDesc& property);
void ClearProperties();
const Containers::Array<ShaderPropertyDesc>& GetProperties() const { return m_properties; }
const ShaderPropertyDesc* FindProperty(const Containers::String& propertyName) const;
void AddPass(const ShaderPass& pass);
void ClearPasses();
Core::uint32 GetPassCount() const { return static_cast<Core::uint32>(m_passes.Size()); }
@@ -105,9 +146,15 @@ public:
const Containers::String& passName,
const Containers::String& tagName,
const Containers::String& tagValue);
void AddPassResourceBinding(
const Containers::String& passName,
const ShaderResourceBindingDesc& binding);
bool HasPass(const Containers::String& passName) const;
const ShaderPass* FindPass(const Containers::String& passName) const;
ShaderPass* FindPass(const Containers::String& passName);
const ShaderResourceBindingDesc* FindPassResourceBinding(
const Containers::String& passName,
const Containers::String& resourceName) const;
const ShaderStageVariant* FindVariant(
const Containers::String& passName,
ShaderType stage,
@@ -129,6 +176,7 @@ private:
Containers::Array<ShaderUniform> m_uniforms;
Containers::Array<ShaderAttribute> m_attributes;
Containers::Array<ShaderPropertyDesc> m_properties;
Containers::Array<ShaderPass> m_passes;
class IRHIShader* m_rhiResource = nullptr;