Add runtime material buffer bindings
This commit is contained in:
@@ -81,6 +81,20 @@ void RemoveTextureBindingByName(
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveBufferBindingByName(
|
||||
Containers::Array<MaterialBufferBinding>& bufferBindings,
|
||||
const Containers::String& name) {
|
||||
for (size_t bindingIndex = 0; bindingIndex < bufferBindings.Size(); ++bindingIndex) {
|
||||
if (bufferBindings[bindingIndex].name == name) {
|
||||
if (bindingIndex != bufferBindings.Size() - 1) {
|
||||
bufferBindings[bindingIndex] = std::move(bufferBindings.Back());
|
||||
}
|
||||
bufferBindings.PopBack();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnsureTextureProperty(Containers::HashMap<Containers::String, MaterialProperty>& properties,
|
||||
const Containers::String& name,
|
||||
MaterialPropertyType type = MaterialPropertyType::Texture) {
|
||||
@@ -329,6 +343,7 @@ void Material::Release() {
|
||||
m_properties.Clear();
|
||||
m_constantLayout.Clear();
|
||||
m_textureBindings.Clear();
|
||||
m_bufferBindings.Clear();
|
||||
m_constantBufferData.Clear();
|
||||
m_changeVersion = 1;
|
||||
m_isValid = false;
|
||||
@@ -338,6 +353,7 @@ void Material::Release() {
|
||||
void Material::SetShader(const ResourceHandle<Shader>& shader) {
|
||||
m_shader = shader;
|
||||
SyncShaderSchemaProperties(true);
|
||||
SyncShaderRuntimeBufferBindings(true);
|
||||
SyncShaderSchemaKeywords(true);
|
||||
MarkChanged(true);
|
||||
}
|
||||
@@ -643,6 +659,36 @@ void Material::SetTexture(const Containers::String& name, const ResourceHandle<T
|
||||
MarkChanged(false);
|
||||
}
|
||||
|
||||
void Material::SetBuffer(const Containers::String& name, RHI::RHIBuffer* buffer) {
|
||||
SetBuffer(name, buffer, MaterialBufferBindingViewDesc());
|
||||
}
|
||||
|
||||
void Material::SetBuffer(
|
||||
const Containers::String& name,
|
||||
RHI::RHIBuffer* buffer,
|
||||
const MaterialBufferBindingViewDesc& viewDesc) {
|
||||
if (buffer == nullptr) {
|
||||
RemoveBufferBinding(name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (MaterialBufferBinding& binding : m_bufferBindings) {
|
||||
if (binding.name == name) {
|
||||
binding.buffer = buffer;
|
||||
binding.viewDesc = viewDesc;
|
||||
MarkChanged(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MaterialBufferBinding binding = {};
|
||||
binding.name = name;
|
||||
binding.buffer = buffer;
|
||||
binding.viewDesc = viewDesc;
|
||||
m_bufferBindings.PushBack(binding);
|
||||
MarkChanged(false);
|
||||
}
|
||||
|
||||
void Material::SetTextureAssetRef(const Containers::String& name,
|
||||
const AssetRef& textureRef,
|
||||
const Containers::String& texturePath) {
|
||||
@@ -785,6 +831,21 @@ ResourceHandle<Texture> Material::GetTexture(const Containers::String& name) con
|
||||
return ResourceHandle<Texture>();
|
||||
}
|
||||
|
||||
RHI::RHIBuffer* Material::GetBuffer(const Containers::String& name) const {
|
||||
const MaterialBufferBinding* binding = FindBufferBinding(name);
|
||||
return binding != nullptr ? binding->buffer : nullptr;
|
||||
}
|
||||
|
||||
const MaterialBufferBinding* Material::FindBufferBinding(const Containers::String& name) const {
|
||||
for (const MaterialBufferBinding& binding : m_bufferBindings) {
|
||||
if (binding.name == name) {
|
||||
return &binding;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Containers::String Material::GetTextureBindingName(Core::uint32 index) const {
|
||||
return index < m_textureBindings.Size() ? m_textureBindings[index].name : Containers::String();
|
||||
}
|
||||
@@ -996,6 +1057,23 @@ void Material::ClearAllProperties() {
|
||||
MarkChanged(true);
|
||||
}
|
||||
|
||||
void Material::RemoveBufferBinding(const Containers::String& name) {
|
||||
const size_t bindingCount = m_bufferBindings.Size();
|
||||
RemoveBufferBindingByName(m_bufferBindings, name);
|
||||
if (m_bufferBindings.Size() != bindingCount) {
|
||||
MarkChanged(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Material::ClearBufferBindings() {
|
||||
if (m_bufferBindings.Empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_bufferBindings.Clear();
|
||||
MarkChanged(false);
|
||||
}
|
||||
|
||||
const ShaderPropertyDesc* Material::FindShaderPropertyDesc(const Containers::String& name) const {
|
||||
if (m_shader.Get() == nullptr) {
|
||||
return nullptr;
|
||||
@@ -1064,6 +1142,52 @@ void Material::SyncShaderSchemaProperties(bool removeUnknownProperties) {
|
||||
}
|
||||
}
|
||||
|
||||
void Material::SyncShaderRuntimeBufferBindings(bool removeUnknownBindings) {
|
||||
if (m_shader.Get() == nullptr || !removeUnknownBindings) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Containers::String> unknownBindings;
|
||||
unknownBindings.reserve(m_bufferBindings.Size());
|
||||
for (const MaterialBufferBinding& binding : m_bufferBindings) {
|
||||
bool found = false;
|
||||
for (const ShaderPass& shaderPass : m_shader->GetPasses()) {
|
||||
for (const ShaderResourceBindingDesc& shaderBinding : shaderPass.resources) {
|
||||
if (shaderBinding.name != binding.name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (shaderBinding.type) {
|
||||
case ShaderResourceType::StructuredBuffer:
|
||||
case ShaderResourceType::RawBuffer:
|
||||
case ShaderResourceType::RWStructuredBuffer:
|
||||
case ShaderResourceType::RWRawBuffer:
|
||||
found = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
unknownBindings.push_back(binding.name);
|
||||
}
|
||||
}
|
||||
|
||||
for (const Containers::String& bindingName : unknownBindings) {
|
||||
RemoveBufferBindingByName(m_bufferBindings, bindingName);
|
||||
}
|
||||
}
|
||||
|
||||
void Material::SyncShaderSchemaKeywords(bool removeUnknownKeywords) {
|
||||
if (m_shader.Get() == nullptr || !removeUnknownKeywords) {
|
||||
return;
|
||||
@@ -1104,6 +1228,7 @@ void Material::UpdateMemorySize() {
|
||||
m_tags.Size() * sizeof(MaterialTagEntry) +
|
||||
m_keywordSet.enabledKeywords.Size() * sizeof(Containers::String) +
|
||||
m_textureBindings.Size() * sizeof(MaterialTextureBinding) +
|
||||
m_bufferBindings.Size() * sizeof(MaterialBufferBinding) +
|
||||
m_properties.Size() * sizeof(MaterialProperty) +
|
||||
m_name.Length() +
|
||||
m_path.Length();
|
||||
@@ -1125,6 +1250,10 @@ void Material::UpdateMemorySize() {
|
||||
m_memorySize += binding.name.Length();
|
||||
m_memorySize += binding.texturePath.Length();
|
||||
}
|
||||
|
||||
for (const MaterialBufferBinding& binding : m_bufferBindings) {
|
||||
m_memorySize += binding.name.Length();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Resources
|
||||
|
||||
Reference in New Issue
Block a user