Formalize material schema and constant layout contract

This commit is contained in:
2026-04-03 16:49:30 +08:00
parent 052ac28aa3
commit 03bd755e0a
10 changed files with 1841 additions and 87 deletions

View File

@@ -7,6 +7,8 @@
#include <XCEngine/Resources/Mesh/Mesh.h>
#include <XCEngine/Rendering/VisibleRenderObject.h>
#include <cstddef>
namespace XCEngine {
namespace Rendering {
@@ -122,6 +124,26 @@ struct BuiltinForwardMaterialData {
Math::Vector4 baseColorFactor = Math::Vector4::One();
};
struct MaterialConstantLayoutView {
const Resources::MaterialConstantFieldDesc* fields = nullptr;
size_t count = 0;
size_t size = 0;
bool IsValid() const {
return fields != nullptr && count > 0 && size > 0;
}
};
struct MaterialConstantPayloadView {
const void* data = nullptr;
size_t size = 0;
MaterialConstantLayoutView layout = {};
bool IsValid() const {
return data != nullptr && size > 0 && layout.IsValid() && layout.size == size;
}
};
inline const Resources::ShaderPropertyDesc* FindShaderPropertyBySemantic(
const Resources::Material* material,
const Containers::String& semantic) {
@@ -220,6 +242,25 @@ inline BuiltinForwardMaterialData BuildBuiltinForwardMaterialData(const Resource
return data;
}
inline MaterialConstantPayloadView ResolveSchemaMaterialConstantPayload(const Resources::Material* material) {
if (material == nullptr || material->GetShader() == nullptr) {
return {};
}
const Containers::Array<Resources::MaterialConstantFieldDesc>& constantLayout = material->GetConstantLayout();
const Containers::Array<Core::uint8>& constantBufferData = material->GetConstantBufferData();
if (constantLayout.Empty() || constantBufferData.Empty()) {
return {};
}
MaterialConstantLayoutView layoutView = {};
layoutView.fields = constantLayout.Data();
layoutView.count = constantLayout.Size();
layoutView.size = constantBufferData.Size();
return { constantBufferData.Data(), constantBufferData.Size(), layoutView };
}
inline const Resources::Material* ResolveMaterial(
const Components::MeshRendererComponent* meshRenderer,
const Resources::Mesh* mesh,

View File

@@ -1,5 +1,6 @@
#pragma once
#include <XCEngine/Core/Asset/IResource.h>
#include <XCEngine/Core/Asset/AssetRef.h>
#include <XCEngine/Core/Asset/ResourceHandle.h>
#include <XCEngine/Core/Asset/ResourceManager.h>
#include <XCEngine/Resources/Texture/Texture.h>
@@ -128,6 +129,14 @@ struct MaterialProperty {
MaterialProperty() : type(MaterialPropertyType::Float), refCount(0) {}
};
struct MaterialConstantFieldDesc {
Containers::String name;
MaterialPropertyType type = MaterialPropertyType::Float;
Core::uint32 offset = 0;
Core::uint32 size = 0;
Core::uint32 alignedSize = 0;
};
struct MaterialTagEntry {
Containers::String name;
Containers::String value;
@@ -143,6 +152,7 @@ struct MaterialTextureBinding {
Containers::String name;
Core::uint32 slot = 0;
ResourceHandle<Texture> texture;
AssetRef textureRef;
Containers::String texturePath;
std::shared_ptr<PendingTextureLoadState> pendingLoad;
};
@@ -190,6 +200,9 @@ public:
void SetInt(const Containers::String& name, Core::int32 value);
void SetBool(const Containers::String& name, bool value);
void SetTexture(const Containers::String& name, const ResourceHandle<Texture>& texture);
void SetTextureAssetRef(const Containers::String& name,
const AssetRef& textureRef,
const Containers::String& texturePath = Containers::String());
void SetTexturePath(const Containers::String& name, const Containers::String& texturePath);
float GetFloat(const Containers::String& name) const;
@@ -201,12 +214,16 @@ public:
ResourceHandle<Texture> GetTexture(const Containers::String& name) const;
Core::uint32 GetTextureBindingCount() const { return static_cast<Core::uint32>(m_textureBindings.Size()); }
Containers::String GetTextureBindingName(Core::uint32 index) const;
AssetRef GetTextureBindingAssetRef(Core::uint32 index) const;
Containers::String GetTextureBindingPath(Core::uint32 index) const;
ResourceHandle<Texture> GetTextureBindingLoadedTexture(Core::uint32 index) const;
ResourceHandle<Texture> GetTextureBindingTexture(Core::uint32 index) const;
const Containers::Array<MaterialTextureBinding>& GetTextureBindings() const { return m_textureBindings; }
std::vector<MaterialProperty> GetProperties() const;
const Containers::Array<Core::uint8>& GetConstantBufferData() const { return m_constantBufferData; }
const Containers::Array<MaterialConstantFieldDesc>& GetConstantLayout() const { return m_constantLayout; }
const MaterialConstantFieldDesc* FindConstantField(const Containers::String& name) const;
void UpdateConstantBuffer();
Core::uint64 GetChangeVersion() const { return m_changeVersion; }
void RecalculateMemorySize();
@@ -216,6 +233,10 @@ public:
void ClearAllProperties();
private:
const ShaderPropertyDesc* FindShaderPropertyDesc(const Containers::String& name) const;
bool CanAssignPropertyType(const Containers::String& name, MaterialPropertyType type) const;
bool ResetPropertyToShaderDefault(const Containers::String& name);
void SyncShaderSchemaProperties(bool removeUnknownProperties);
void BeginAsyncTextureLoad(Core::uint32 index);
void ResolvePendingTextureBinding(Core::uint32 index);
void ResolvePendingTextureBindings();
@@ -228,6 +249,7 @@ private:
Containers::String m_shaderPass;
Containers::Array<MaterialTagEntry> m_tags;
Containers::HashMap<Containers::String, MaterialProperty> m_properties;
Containers::Array<MaterialConstantFieldDesc> m_constantLayout;
Containers::Array<Core::uint8> m_constantBufferData;
Containers::Array<MaterialTextureBinding> m_textureBindings;
Core::uint64 m_changeVersion = 1;