These changes make material system report warnings when gameplay scripts attempt to change PSO-impacting material properties at runtime. So far the material system has always allowed any properties to be changed at runtime, including those that affect Pipeline State Objects (PSOs), as this is supported on several platforms. But some platforms require that Pipeline State Objects be pre-compiled and shipped with the game. At some point we will need to add new restrictions that limit what material properties can be changed at runtime. In the meantime, these warnings should alert users to avoid this, as the functionality likely won't be supported in the future.
- Made the Material and LuaMaterialFunctor classes configurable to report errors or warnings when material properties modify Pipeline State Objects. This is controlled by a new "MaterialPropertyPsoHandling" enum. - Made the EditorMaterialComponent override PSO handling as Enabled, to prevent warnings when the user is editing material instance property overrides. This requried a new MaterialComponentNotificationBus bus message "OnMaterialInstanceCreated". - Removed unnecessary GetMaterialPropertyDependencies member from material functor context classes, as this is already available as part of the functor itself. - Made Material::SetPropertyValue return early when the property value hadn't actually changed. Besides being more efficientn, this prevents unnecessary spamming of the new warning. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
This commit is contained in:
@@ -128,7 +128,7 @@ namespace AZ
|
||||
|
||||
if (m_scriptStatus == ScriptStatus::Ready)
|
||||
{
|
||||
LuaMaterialFunctorRuntimeContext luaContext{&context, m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix};
|
||||
LuaMaterialFunctorRuntimeContext luaContext{&context, &GetMaterialPropertyDependencies(), m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix};
|
||||
AZ::ScriptDataContext call;
|
||||
if (m_scriptContext->Call("Process", call))
|
||||
{
|
||||
@@ -146,7 +146,7 @@ namespace AZ
|
||||
|
||||
if (m_scriptStatus == ScriptStatus::Ready)
|
||||
{
|
||||
LuaMaterialFunctorEditorContext luaContext{&context, m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix};
|
||||
LuaMaterialFunctorEditorContext luaContext{&context, &GetMaterialPropertyDependencies(), m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix};
|
||||
AZ::ScriptDataContext call;
|
||||
if (m_scriptContext->Call("ProcessEditor", call))
|
||||
{
|
||||
@@ -157,10 +157,12 @@ namespace AZ
|
||||
}
|
||||
|
||||
LuaMaterialFunctorCommonContext::LuaMaterialFunctorCommonContext(MaterialFunctor::RuntimeContext* runtimeContextImpl,
|
||||
const MaterialPropertyFlags* materialPropertyDependencies,
|
||||
const AZStd::string& propertyNamePrefix,
|
||||
const AZStd::string& srgNamePrefix,
|
||||
const AZStd::string& optionsNamePrefix)
|
||||
: m_runtimeContextImpl(runtimeContextImpl)
|
||||
, m_materialPropertyDependencies(materialPropertyDependencies)
|
||||
, m_propertyNamePrefix(propertyNamePrefix)
|
||||
, m_srgNamePrefix(srgNamePrefix)
|
||||
, m_optionsNamePrefix(optionsNamePrefix)
|
||||
@@ -168,34 +170,96 @@ namespace AZ
|
||||
}
|
||||
|
||||
LuaMaterialFunctorCommonContext::LuaMaterialFunctorCommonContext(MaterialFunctor::EditorContext* editorContextImpl,
|
||||
const MaterialPropertyFlags* materialPropertyDependencies,
|
||||
const AZStd::string& propertyNamePrefix,
|
||||
const AZStd::string& srgNamePrefix,
|
||||
const AZStd::string& optionsNamePrefix)
|
||||
: m_editorContextImpl(editorContextImpl)
|
||||
, m_materialPropertyDependencies(materialPropertyDependencies)
|
||||
, m_propertyNamePrefix(propertyNamePrefix)
|
||||
, m_srgNamePrefix(srgNamePrefix)
|
||||
, m_optionsNamePrefix(optionsNamePrefix)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialPropertyPsoHandling LuaMaterialFunctorCommonContext::GetMaterialPropertyPsoHandling() const
|
||||
{
|
||||
if (m_runtimeContextImpl)
|
||||
{
|
||||
return m_runtimeContextImpl->GetMaterialPropertyPsoHandling();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_editorContextImpl->GetMaterialPropertyPsoHandling();
|
||||
}
|
||||
}
|
||||
|
||||
RHI::ConstPtr<MaterialPropertiesLayout> LuaMaterialFunctorCommonContext::GetMaterialPropertiesLayout() const
|
||||
{
|
||||
if (m_runtimeContextImpl)
|
||||
{
|
||||
return m_runtimeContextImpl->GetMaterialPropertiesLayout();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_editorContextImpl->GetMaterialPropertiesLayout();
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string LuaMaterialFunctorCommonContext::GetMaterialPropertyDependenciesString() const
|
||||
{
|
||||
AZStd::vector<AZStd::string> propertyList;
|
||||
for (size_t i = 0; i < m_materialPropertyDependencies->size(); ++i)
|
||||
{
|
||||
if ((*m_materialPropertyDependencies)[i])
|
||||
{
|
||||
propertyList.push_back(GetMaterialPropertiesLayout()->GetPropertyDescriptor(MaterialPropertyIndex{i})->GetName().GetStringView());
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string propertyListString;
|
||||
AzFramework::StringFunc::Join(propertyListString, propertyList.begin(), propertyList.end(), ", ");
|
||||
|
||||
return propertyListString;
|
||||
}
|
||||
|
||||
bool LuaMaterialFunctorCommonContext::CheckPsoChangesAllowed()
|
||||
{
|
||||
if (GetMaterialPropertyPsoHandling() == MaterialPropertyPsoHandling::Error)
|
||||
{
|
||||
if (!m_psoChangesReported)
|
||||
{
|
||||
LuaMaterialFunctorUtilities::Script_Error(
|
||||
AZStd::string::format(
|
||||
"The following material properties must not be changed at runtime because they impact Pipeline State Objects: %s", GetMaterialPropertyDependenciesString().c_str()));
|
||||
|
||||
m_psoChangesReported = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (GetMaterialPropertyPsoHandling() == MaterialPropertyPsoHandling::Warning)
|
||||
{
|
||||
if (!m_psoChangesReported)
|
||||
{
|
||||
LuaMaterialFunctorUtilities::Script_Warning(
|
||||
AZStd::string::format(
|
||||
"The following material properties should not be changed at runtime because they impact Pipeline State Objects: %s", GetMaterialPropertyDependenciesString().c_str()));
|
||||
|
||||
m_psoChangesReported = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MaterialPropertyIndex LuaMaterialFunctorCommonContext::GetMaterialPropertyIndex(const char* name, const char* functionName) const
|
||||
{
|
||||
MaterialPropertyIndex propertyIndex;
|
||||
|
||||
Name propertyFullName{m_propertyNamePrefix + name};
|
||||
|
||||
if (m_runtimeContextImpl)
|
||||
{
|
||||
propertyIndex = m_runtimeContextImpl->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyFullName);
|
||||
}
|
||||
else if (m_editorContextImpl)
|
||||
{
|
||||
propertyIndex = m_editorContextImpl->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyFullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Context not initialized properly");
|
||||
}
|
||||
|
||||
propertyIndex = GetMaterialPropertiesLayout()->FindPropertyIndex(propertyFullName);
|
||||
|
||||
if (!propertyIndex.IsValid())
|
||||
{
|
||||
@@ -297,10 +361,11 @@ namespace AZ
|
||||
}
|
||||
|
||||
LuaMaterialFunctorRuntimeContext::LuaMaterialFunctorRuntimeContext(MaterialFunctor::RuntimeContext* runtimeContextImpl,
|
||||
const MaterialPropertyFlags* materialPropertyDependencies,
|
||||
const AZStd::string& propertyNamePrefix,
|
||||
const AZStd::string& srgNamePrefix,
|
||||
const AZStd::string& optionsNamePrefix)
|
||||
: LuaMaterialFunctorCommonContext(runtimeContextImpl, propertyNamePrefix, srgNamePrefix, optionsNamePrefix)
|
||||
: LuaMaterialFunctorCommonContext(runtimeContextImpl, materialPropertyDependencies, propertyNamePrefix, srgNamePrefix, optionsNamePrefix)
|
||||
, m_runtimeContextImpl(runtimeContextImpl)
|
||||
{
|
||||
}
|
||||
@@ -331,7 +396,7 @@ namespace AZ
|
||||
|
||||
if (!shaderItem.MaterialOwnsShaderOption(optionIndex))
|
||||
{
|
||||
LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format("Shader option '%s' is not owned by this material.", fullOptionName.GetCStr()).c_str());
|
||||
LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format("Shader option '%s' is not owned by this material.", fullOptionName.GetCStr()));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -398,12 +463,12 @@ namespace AZ
|
||||
{
|
||||
if (index < GetShaderCount())
|
||||
{
|
||||
return LuaMaterialFunctorShaderItem{&(*m_runtimeContextImpl->m_shaderCollection)[index]};
|
||||
return LuaMaterialFunctorShaderItem{this, &(*m_runtimeContextImpl->m_shaderCollection)[index]};
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format("GetShader(%zu) is invalid.", index));
|
||||
return LuaMaterialFunctorShaderItem{nullptr};
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,13 +477,13 @@ namespace AZ
|
||||
const AZ::Name tag{shaderTag};
|
||||
if (m_runtimeContextImpl->m_shaderCollection->HasShaderTag(tag))
|
||||
{
|
||||
return LuaMaterialFunctorShaderItem{&(*m_runtimeContextImpl->m_shaderCollection)[tag]};
|
||||
return LuaMaterialFunctorShaderItem{this, &(*m_runtimeContextImpl->m_shaderCollection)[tag]};
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format(
|
||||
"GetShaderByTag('%s') is invalid: Could not find a shader with the tag '%s'.", tag.GetCStr(), tag.GetCStr()));
|
||||
return LuaMaterialFunctorShaderItem{nullptr};
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,10 +524,11 @@ namespace AZ
|
||||
}
|
||||
|
||||
LuaMaterialFunctorEditorContext::LuaMaterialFunctorEditorContext(MaterialFunctor::EditorContext* editorContextImpl,
|
||||
const MaterialPropertyFlags* materialPropertyDependencies,
|
||||
const AZStd::string& propertyNamePrefix,
|
||||
const AZStd::string& srgNamePrefix,
|
||||
const AZStd::string& optionsNamePrefix)
|
||||
: LuaMaterialFunctorCommonContext(editorContextImpl, propertyNamePrefix, srgNamePrefix, optionsNamePrefix)
|
||||
: LuaMaterialFunctorCommonContext(editorContextImpl, materialPropertyDependencies, propertyNamePrefix, srgNamePrefix, optionsNamePrefix)
|
||||
, m_editorContextImpl(editorContextImpl)
|
||||
{
|
||||
}
|
||||
@@ -595,7 +661,7 @@ namespace AZ
|
||||
|
||||
LuaMaterialFunctorRenderStates LuaMaterialFunctorShaderItem::GetRenderStatesOverride()
|
||||
{
|
||||
if (m_shaderItem)
|
||||
if (m_context->CheckPsoChangesAllowed() && m_shaderItem)
|
||||
{
|
||||
return LuaMaterialFunctorRenderStates{m_shaderItem->GetRenderStatesOverlay()};
|
||||
}
|
||||
@@ -638,8 +704,7 @@ namespace AZ
|
||||
{
|
||||
LuaMaterialFunctorUtilities::Script_Error(
|
||||
AZStd::string::format(
|
||||
"Shader option '%s' is not owned by the shader '%s'.", name.GetCStr(), m_shaderItem->GetShaderTag().GetCStr())
|
||||
.c_str());
|
||||
"Shader option '%s' is not owned by the shader '%s'.", name.GetCStr(), m_shaderItem->GetShaderTag().GetCStr()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user