You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1186 lines
56 KiB
C++
1186 lines
56 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AzTest/AzTest.h>
|
|
#include <Common/RPITestFixture.h>
|
|
#include <Common/JsonTestUtils.h>
|
|
#include <Common/ErrorMessageFinder.h>
|
|
#include <Common/ShaderAssetTestUtils.h>
|
|
#include <AzCore/Script/ScriptAsset.h>
|
|
#include <Atom/RPI.Edit/Material/LuaMaterialFunctorSourceData.h>
|
|
#include <Atom/RPI.Reflect/Material/LuaMaterialFunctor.h>
|
|
#include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
|
|
#include <Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h>
|
|
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
|
#include <Atom/RPI.Reflect/Material/MaterialAssetCreator.h>
|
|
#include <Atom/RPI.Public/Material/Material.h>
|
|
#include <Material/MaterialAssetTestUtils.h>
|
|
|
|
namespace UnitTest
|
|
{
|
|
using namespace AZ;
|
|
using namespace RPI;
|
|
|
|
class LuaMaterialFunctorTests
|
|
: public RPITestFixture
|
|
{
|
|
public:
|
|
static void AddLuaFunctor(MaterialTypeAssetCreator& materialTypeCreator, const AZStd::string& script)
|
|
{
|
|
LuaMaterialFunctorSourceData functorSourceData;
|
|
functorSourceData.m_luaScript = script;
|
|
|
|
MaterialNameContext nameContext;
|
|
|
|
MaterialFunctorSourceData::RuntimeContext createFunctorContext{
|
|
"Dummy.materialtype",
|
|
materialTypeCreator.GetMaterialPropertiesLayout(),
|
|
materialTypeCreator.GetMaterialShaderResourceGroupLayout(),
|
|
materialTypeCreator.GetShaderCollection(),
|
|
&nameContext
|
|
};
|
|
|
|
MaterialFunctorSourceData::FunctorResult result = functorSourceData.CreateFunctor(createFunctorContext);
|
|
EXPECT_TRUE(result.IsSuccess());
|
|
|
|
if (result.IsSuccess())
|
|
{
|
|
materialTypeCreator.AddMaterialFunctor(result.GetValue());
|
|
|
|
for (auto& shaderOption : functorSourceData.GetShaderOptionDependencies())
|
|
{
|
|
materialTypeCreator.ClaimShaderOptionOwnership(shaderOption);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
protected:
|
|
void SetUp() override
|
|
{
|
|
RPITestFixture::SetUp();
|
|
}
|
|
|
|
void TearDown() override
|
|
{
|
|
RPITestFixture::TearDown();
|
|
}
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> CreateCommonTestShaderOptionsLayout()
|
|
{
|
|
AZStd::vector<RPI::ShaderOptionValuePair> boolOptionValues = CreateBoolShaderOptionValues();
|
|
AZStd::vector<RPI::ShaderOptionValuePair> intRangeOptionValues = CreateIntRangeShaderOptionValues(0, 15);
|
|
AZStd::vector<RPI::ShaderOptionValuePair> qualityOptionValues = CreateEnumShaderOptionValues({"Quality::Low", "Quality::Medium", "Quality::High"});
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> shaderOptions = RPI::ShaderOptionGroupLayout::Create();
|
|
shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_bool"}, ShaderOptionType::Boolean, 0, 0, boolOptionValues, Name{"False"}});
|
|
shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_uint"}, ShaderOptionType::IntegerRange, 1, 1, intRangeOptionValues, Name{"0"}});
|
|
shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_enum"}, ShaderOptionType::Enumeration, 5, 2, qualityOptionValues, Name{"Quality::Low"}});
|
|
shaderOptions->Finalize();
|
|
|
|
return shaderOptions;
|
|
}
|
|
};
|
|
|
|
class TestMaterialData
|
|
{
|
|
public:
|
|
// Setup for a single material property and nothing else, used in particular to test setting render states
|
|
void Setup(
|
|
MaterialPropertyDataType dataType,
|
|
const char* materialPropertyName,
|
|
const char* luaFunctorScript)
|
|
{
|
|
MaterialTypeAssetCreator materialTypeCreator;
|
|
materialTypeCreator.Begin(Uuid::CreateRandom());
|
|
materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()), Name{"TestShader"});
|
|
materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
|
|
materialTypeCreator.EndMaterialProperty();
|
|
LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
|
|
EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
|
|
|
|
Data::Asset<MaterialAsset> materialAsset;
|
|
MaterialAssetCreator materialCreator;
|
|
materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset, true);
|
|
EXPECT_TRUE(materialCreator.End(materialAsset));
|
|
|
|
m_material = Material::Create(materialAsset);
|
|
|
|
m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
|
|
}
|
|
|
|
// Setup for a single material property and a specific shader constant input
|
|
void Setup(
|
|
RHI::Ptr<RHI::ShaderResourceGroupLayout> materialSrgLayout,
|
|
MaterialPropertyDataType dataType,
|
|
const char* materialPropertyName,
|
|
const char* shaderInputName,
|
|
const char* luaFunctorScript)
|
|
{
|
|
MaterialTypeAssetCreator materialTypeCreator;
|
|
materialTypeCreator.Begin(Uuid::CreateRandom());
|
|
materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout));
|
|
materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
|
|
materialTypeCreator.EndMaterialProperty();
|
|
LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
|
|
EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
|
|
|
|
Data::Asset<MaterialAsset> materialAsset;
|
|
MaterialAssetCreator materialCreator;
|
|
materialCreator.Begin(Uuid::CreateRandom(),m_materialTypeAsset, true);
|
|
EXPECT_TRUE(materialCreator.End(materialAsset));
|
|
|
|
m_material = Material::Create(materialAsset);
|
|
|
|
m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
|
|
m_srgConstantIndex = m_material->GetRHIShaderResourceGroup()->GetData().FindShaderInputConstantIndex(Name{shaderInputName});
|
|
}
|
|
|
|
// Setup for a single material property and a specific shader option
|
|
void Setup(
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> shaderOptionsLayout,
|
|
MaterialPropertyDataType dataType,
|
|
const char* materialPropertyName,
|
|
const char* shaderOptionName,
|
|
const char* luaFunctorScript)
|
|
{
|
|
MaterialTypeAssetCreator materialTypeCreator;
|
|
materialTypeCreator.Begin(Uuid::CreateRandom());
|
|
materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom(), {}, shaderOptionsLayout), Name{"TestShader"});
|
|
materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
|
|
materialTypeCreator.EndMaterialProperty();
|
|
LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
|
|
EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
|
|
|
|
Data::Asset<MaterialAsset> materialAsset;
|
|
MaterialAssetCreator materialCreator;
|
|
materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset, true);
|
|
EXPECT_TRUE(materialCreator.End(materialAsset));
|
|
|
|
m_material = Material::Create(materialAsset);
|
|
|
|
m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
|
|
m_shaderOptionIndex = shaderOptionsLayout->FindShaderOptionIndex(Name{shaderOptionName});
|
|
}
|
|
|
|
// Setup for two material properties for testing one property affecting another property's metadata
|
|
void Setup(
|
|
MaterialPropertyDataType primaryPropertyDataType,
|
|
const char* primaryPropertyName,
|
|
MaterialPropertyDataType secondaryPropertyDataType,
|
|
const char* secondaryPropertyName,
|
|
const char* luaFunctorScript)
|
|
{
|
|
MaterialTypeAssetCreator materialTypeCreator;
|
|
materialTypeCreator.Begin(Uuid::CreateRandom());
|
|
materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()));
|
|
materialTypeCreator.BeginMaterialProperty(Name{primaryPropertyName}, primaryPropertyDataType);
|
|
materialTypeCreator.EndMaterialProperty();
|
|
materialTypeCreator.BeginMaterialProperty(Name{secondaryPropertyName}, secondaryPropertyDataType);
|
|
materialTypeCreator.EndMaterialProperty();
|
|
LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
|
|
EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
|
|
|
|
Data::Asset<MaterialAsset> materialAsset;
|
|
MaterialAssetCreator materialCreator;
|
|
materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset, true);
|
|
EXPECT_TRUE(materialCreator.End(materialAsset));
|
|
|
|
m_material = Material::Create(materialAsset);
|
|
|
|
m_materialPropertyIndex = m_material->FindPropertyIndex(Name{primaryPropertyName});
|
|
m_otherMaterialPropertyIndex = m_material->FindPropertyIndex(Name{secondaryPropertyName});
|
|
}
|
|
|
|
Data::Asset<MaterialTypeAsset> GetMaterialTypeAsset() { return m_materialTypeAsset; }
|
|
Data::Instance<Material> GetMaterial() { return m_material; }
|
|
MaterialPropertyIndex GetMaterialPropertyIndex() { return m_materialPropertyIndex; }
|
|
MaterialPropertyIndex GetOtherMaterialPropertyIndex() { return m_otherMaterialPropertyIndex; }
|
|
RHI::ShaderInputConstantIndex GetSrgConstantIndex() { return m_srgConstantIndex; }
|
|
ShaderOptionIndex GetShaderOptionIndex() { return m_shaderOptionIndex; }
|
|
|
|
private:
|
|
Data::Asset<MaterialTypeAsset> m_materialTypeAsset;
|
|
Data::Instance<Material> m_material;
|
|
MaterialPropertyIndex m_materialPropertyIndex;
|
|
MaterialPropertyIndex m_otherMaterialPropertyIndex;
|
|
RHI::ShaderInputConstantIndex m_srgConstantIndex;
|
|
ShaderOptionIndex m_shaderOptionIndex;
|
|
};
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Bool)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestBool"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_bool("general.TestBool")
|
|
context:SetShaderConstant_bool("m_bool", value)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Bool, "general.TestBool", "m_bool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(true, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<bool>(testData.GetSrgConstantIndex()));
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(false, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<bool>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Float)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestFloat"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_float("general.TestFloat")
|
|
context:SetShaderConstant_float("m_float", value * 2.0)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Float, "general.TestFloat", "m_float", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1.25f});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_FLOAT_EQ(2.5f, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<float>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Int)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestInt"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_int("general.TestInt")
|
|
context:SetShaderConstant_int("m_int", value * -1)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Int, "general.TestInt", "m_int", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{2});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(-2, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<int32_t>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_UInt)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestUInt"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_uint("general.TestUInt")
|
|
context:SetShaderConstant_uint("m_uint", value + 5)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::UInt, "general.TestUInt", "m_uint", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{2u});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(7, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<uint32_t>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Float2)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestVector2"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_Vector2("general.TestVector2")
|
|
local swap = value.y
|
|
value.y = value.x
|
|
value.x = swap
|
|
context:SetShaderConstant_Vector2("m_float2", value)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector2, "general.TestVector2", "m_float2", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector2(1.0f, 2.0f)});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(Vector2(2.0f, 1.0f), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Vector2>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Vector3)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestVector3"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_Vector3("general.TestVector3")
|
|
value:Normalize()
|
|
context:SetShaderConstant_Vector3("m_float3", value)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector3, "general.TestVector3", "m_float3", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector3(5.0f, 4.0f, 3.0f)});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(Vector3(5.0f, 4.0f, 3.0f).GetNormalized(), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Vector3>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Vector4)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestVector4"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_Vector4("general.TestVector4")
|
|
value:Homogenize()
|
|
context:SetShaderConstant_Vector4("m_float4", value)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector4, "general.TestVector4", "m_float4", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector4(1.0f, 2.0f, 3.0f, 4.0f)});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(Vector4(1.0f, 2.0f, 3.0f, 4.0f) / 4.0f, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Vector4>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Color)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestColor"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_Color("general.TestColor")
|
|
value.r = value.r * value.a
|
|
value.g = value.g * value.a
|
|
value.b = value.b * value.a
|
|
context:SetShaderConstant_Color("m_color", value)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Color, "general.TestColor", "m_color", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Color(1.0f, 0.5f, 0.4f, 0.5f)});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(Color(0.5f, 0.25f, 0.2f, 0.5f), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Color>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderConstant_Matrix3x3)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.Scale"}
|
|
end
|
|
|
|
function Process(context)
|
|
local scale = context:GetMaterialPropertyValue_float("general.Scale")
|
|
local tansform = Matrix3x3.CreateScale(Vector3(scale, scale, 1.0))
|
|
context:SetShaderConstant_Matrix3x3("m_float3x3", tansform)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Float, "general.Scale", "m_float3x3", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0.5f});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(Matrix3x3::CreateScale(Vector3(0.5f, 0.5f, 1.0f)), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Matrix3x3>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderConstant_Matrix4x4)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.Offset"}
|
|
end
|
|
|
|
function Process(context)
|
|
local offset = context:GetMaterialPropertyValue_Vector3("general.Offset")
|
|
local tansform = Matrix4x4.CreateTranslation(offset)
|
|
context:SetShaderConstant_Matrix4x4("m_float4x4", tansform)
|
|
end
|
|
)";
|
|
|
|
auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
|
|
auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector3, "general.Offset", "m_float4x4", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector3(1.0f, 2.0f, 3.0f)});
|
|
ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(Matrix4x4::CreateTranslation(Vector3(1.0f, 2.0f, 3.0f)), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Matrix4x4>(testData.GetSrgConstantIndex()));
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderOption_Bool)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestBool"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {"o_bool"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_bool("general.TestBool")
|
|
context:SetShaderOptionValue_bool("o_bool", value)
|
|
end
|
|
)";
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(options, MaterialPropertyDataType::Bool, "general.TestBool", "o_bool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(1, testData.GetMaterial()->GetShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(0, testData.GetMaterial()->GetShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderOption_UInt)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestInt"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {"o_uint"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_int("general.TestInt")
|
|
context:SetShaderOptionValue_uint("o_uint", value * 2)
|
|
end
|
|
)";
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(options, MaterialPropertyDataType::Int, "general.TestInt", "o_uint", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{6});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(12, testData.GetMaterial()->GetShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_uint"}).GetIndex());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderOption_Enum)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.UseHighQuality"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {"o_enum"}
|
|
end
|
|
|
|
function Process(context)
|
|
local useHighQuality = context:GetMaterialPropertyValue_bool("general.UseHighQuality")
|
|
if (useHighQuality) then
|
|
context:SetShaderOptionValue_enum("o_enum", "Quality::High")
|
|
else
|
|
context:SetShaderOptionValue_enum("o_enum", "Quality::Medium")
|
|
end
|
|
end
|
|
)";
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(options, MaterialPropertyDataType::Bool, "general.UseHighQuality", "o_enum", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(2, testData.GetMaterial()->GetShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(1, testData.GetMaterial()->GetShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_ShaderItem_SetShaderOption_Bool)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestBool"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {"o_bool"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_bool("general.TestBool")
|
|
context:GetShaderByTag("TestShader"):SetShaderOptionValue_bool("o_bool", value)
|
|
end
|
|
)";
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(options, MaterialPropertyDataType::Bool, "general.TestBool", "o_bool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(
|
|
1, testData.GetMaterial()->GetShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(
|
|
0, testData.GetMaterial()->GetShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_ShaderItem_SetShaderOption_UInt)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.TestInt"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {"o_uint"}
|
|
end
|
|
|
|
function Process(context)
|
|
local value = context:GetMaterialPropertyValue_int("general.TestInt")
|
|
context:GetShaderByTag("TestShader"):SetShaderOptionValue_uint("o_uint", value * 2)
|
|
end
|
|
)";
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(options, MaterialPropertyDataType::Int, "general.TestInt", "o_uint", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{6});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(
|
|
12, testData.GetMaterial()->GetShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_uint"}).GetIndex());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_ShaderItem_SetShaderOption_Enum)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.UseHighQuality"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {"o_enum"}
|
|
end
|
|
|
|
function Process(context)
|
|
local useHighQuality = context:GetMaterialPropertyValue_bool("general.UseHighQuality")
|
|
if (useHighQuality) then
|
|
context:GetShaderByTag("TestShader"):SetShaderOptionValue_enum("o_enum", "Quality::High")
|
|
else
|
|
context:GetShaderByTag("TestShader"):SetShaderOptionValue_enum("o_enum", "Quality::Medium")
|
|
end
|
|
end
|
|
)";
|
|
|
|
AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(options, MaterialPropertyDataType::Bool, "general.UseHighQuality", "o_enum", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(
|
|
2, testData.GetMaterial()->GetShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
EXPECT_EQ(
|
|
1, testData.GetMaterial()->GetShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_EditorContext_SetMaterialPropertyVisibility)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return { "general.mode" }
|
|
end
|
|
|
|
function ProcessEditor(context)
|
|
local mode = context:GetMaterialPropertyValue_uint("general.mode")
|
|
|
|
if (mode == 1) then
|
|
context:SetMaterialPropertyVisibility("general.value", MaterialPropertyVisibility_Enabled)
|
|
elseif (mode == 2) then
|
|
context:SetMaterialPropertyVisibility("general.value", MaterialPropertyVisibility_Disabled)
|
|
else
|
|
context:SetMaterialPropertyVisibility("general.value", MaterialPropertyVisibility_Hidden)
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(
|
|
MaterialPropertyDataType::UInt, "general.mode",
|
|
MaterialPropertyDataType::Float, "general.value",
|
|
functorScript);
|
|
|
|
AZStd::unordered_set<AZ::Name> changedPropertyNames;
|
|
AZStd::unordered_map<Name, MaterialPropertyDynamicMetadata> propertyDynamicMetadata;
|
|
propertyDynamicMetadata[Name{"general.mode"}] = {};
|
|
propertyDynamicMetadata[Name{"general.value"}] = {};
|
|
|
|
AZStd::unordered_set<AZ::Name> changedPropertyGroupNames;
|
|
AZStd::unordered_map<Name, MaterialPropertyGroupDynamicMetadata> propertyGroupDynamicMetadata;
|
|
propertyGroupDynamicMetadata[Name{"general"}] = {};
|
|
|
|
Ptr<MaterialFunctor> functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0];
|
|
|
|
AZ::RPI::MaterialFunctor::EditorContext context = AZ::RPI::MaterialFunctor::EditorContext(
|
|
testData.GetMaterial()->GetPropertyValues(),
|
|
testData.GetMaterial()->GetMaterialPropertiesLayout(),
|
|
propertyDynamicMetadata,
|
|
propertyGroupDynamicMetadata,
|
|
changedPropertyNames,
|
|
changedPropertyGroupNames,
|
|
&functor->GetMaterialPropertyDependencies()
|
|
);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u});
|
|
functor->Process(context);
|
|
EXPECT_EQ(MaterialPropertyVisibility::Hidden, propertyDynamicMetadata[Name{"general.value"}].m_visibility);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u});
|
|
functor->Process(context);
|
|
EXPECT_EQ(MaterialPropertyVisibility::Enabled, propertyDynamicMetadata[Name{"general.value"}].m_visibility);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{2u});
|
|
functor->Process(context);
|
|
EXPECT_EQ(MaterialPropertyVisibility::Disabled, propertyDynamicMetadata[Name{"general.value"}].m_visibility);
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_EditorContext_SetMaterialPropertyDescriptionAndRanges)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return { "general.units" }
|
|
end
|
|
|
|
function ProcessEditor(context)
|
|
local units = context:GetMaterialPropertyValue_uint("general.units")
|
|
|
|
if (units == 0) then
|
|
context:SetMaterialPropertyDescription("general.distance", "Distance in meters")
|
|
context:SetMaterialPropertyMinValue_float("general.distance", -10)
|
|
context:SetMaterialPropertyMaxValue_float("general.distance", 10)
|
|
context:SetMaterialPropertySoftMinValue_float("general.distance", -1)
|
|
context:SetMaterialPropertySoftMaxValue_float("general.distance", 1)
|
|
else
|
|
context:SetMaterialPropertyDescription("general.distance", "Distance in centimeters")
|
|
context:SetMaterialPropertyMinValue_float("general.distance", -1000)
|
|
context:SetMaterialPropertyMaxValue_float("general.distance", 1000)
|
|
context:SetMaterialPropertySoftMinValue_float("general.distance", -100)
|
|
context:SetMaterialPropertySoftMaxValue_float("general.distance", 100)
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(
|
|
MaterialPropertyDataType::UInt, "general.units",
|
|
MaterialPropertyDataType::Float, "general.distance",
|
|
functorScript);
|
|
|
|
AZStd::unordered_set<AZ::Name> changedPropertyNames;
|
|
AZStd::unordered_map<Name, MaterialPropertyDynamicMetadata> propertyDynamicMetadata;
|
|
propertyDynamicMetadata[Name{"general.units"}] = {};
|
|
propertyDynamicMetadata[Name{"general.distance"}] = {};
|
|
|
|
AZStd::unordered_set<AZ::Name> changedPropertyGroupNames;
|
|
AZStd::unordered_map<Name, MaterialPropertyGroupDynamicMetadata> propertyGroupDynamicMetadata;
|
|
propertyGroupDynamicMetadata[Name{"general"}] = {};
|
|
|
|
Ptr<MaterialFunctor> functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0];
|
|
|
|
AZ::RPI::MaterialFunctor::EditorContext context = AZ::RPI::MaterialFunctor::EditorContext(
|
|
testData.GetMaterial()->GetPropertyValues(),
|
|
testData.GetMaterial()->GetMaterialPropertiesLayout(),
|
|
propertyDynamicMetadata,
|
|
propertyGroupDynamicMetadata,
|
|
changedPropertyNames,
|
|
changedPropertyGroupNames,
|
|
&functor->GetMaterialPropertyDependencies()
|
|
);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u});
|
|
functor->Process(context);
|
|
EXPECT_STREQ("Distance in meters", propertyDynamicMetadata[Name{"general.distance"}].m_description.c_str());
|
|
EXPECT_EQ(-10.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_min.GetValue<float>());
|
|
EXPECT_EQ(10.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_max.GetValue<float>());
|
|
EXPECT_EQ(-1.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMin.GetValue<float>());
|
|
EXPECT_EQ(1.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMax.GetValue<float>());
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u});
|
|
functor->Process(context);
|
|
EXPECT_STREQ("Distance in centimeters", propertyDynamicMetadata[Name{"general.distance"}].m_description.c_str());
|
|
EXPECT_EQ(-1000.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_min.GetValue<float>());
|
|
EXPECT_EQ(1000.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_max.GetValue<float>());
|
|
EXPECT_EQ(-100.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMin.GetValue<float>());
|
|
EXPECT_EQ(100.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMax.GetValue<float>());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_EditorContext_SetMaterialPropertyGroupVisibility)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return { "general.mode" }
|
|
end
|
|
|
|
function ProcessEditor(context)
|
|
local mode = context:GetMaterialPropertyValue_uint("general.mode")
|
|
|
|
if (mode == 1) then
|
|
context:SetMaterialPropertyGroupVisibility("otherGroup", MaterialPropertyGroupVisibility_Enabled)
|
|
else
|
|
context:SetMaterialPropertyGroupVisibility("otherGroup", MaterialPropertyGroupVisibility_Hidden)
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(
|
|
MaterialPropertyDataType::UInt, "general.mode",
|
|
MaterialPropertyDataType::Float, "otherGroup.value",
|
|
functorScript);
|
|
|
|
AZStd::unordered_set<AZ::Name> changedPropertyNames;
|
|
AZStd::unordered_map<Name, MaterialPropertyDynamicMetadata> propertyDynamicMetadata;
|
|
propertyDynamicMetadata[Name{"general.mode"}] = {};
|
|
propertyDynamicMetadata[Name{"otherGroup.value"}] = {};
|
|
|
|
AZStd::unordered_set<AZ::Name> changedPropertyGroupNames;
|
|
AZStd::unordered_map<Name, MaterialPropertyGroupDynamicMetadata> propertyGroupDynamicMetadata;
|
|
propertyGroupDynamicMetadata[Name{"general"}] = {};
|
|
propertyGroupDynamicMetadata[Name{"otherGroup"}] = {};
|
|
|
|
Ptr<MaterialFunctor> functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0];
|
|
|
|
AZ::RPI::MaterialFunctor::EditorContext context = AZ::RPI::MaterialFunctor::EditorContext(
|
|
testData.GetMaterial()->GetPropertyValues(),
|
|
testData.GetMaterial()->GetMaterialPropertiesLayout(),
|
|
propertyDynamicMetadata,
|
|
propertyGroupDynamicMetadata,
|
|
changedPropertyNames,
|
|
changedPropertyGroupNames,
|
|
&functor->GetMaterialPropertyDependencies()
|
|
);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u});
|
|
functor->Process(context);
|
|
EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"general"}].m_visibility);
|
|
EXPECT_EQ(MaterialPropertyGroupVisibility::Hidden, propertyGroupDynamicMetadata[Name{"otherGroup"}].m_visibility);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u});
|
|
functor->Process(context);
|
|
EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"general"}].m_visibility);
|
|
EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"otherGroup"}].m_visibility);
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetRenderStates)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
// We aren't testing every single render state here, but just getting a representative set...
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.MyBool"}
|
|
end
|
|
|
|
function Process(context)
|
|
local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
|
|
if(boolValue) then
|
|
context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPositionCount(1)
|
|
context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPosition(0, 2, 4)
|
|
context:GetShader(0):GetRenderStatesOverride():SetCullMode(CullMode_None)
|
|
context:GetShader(0):GetRenderStatesOverride():SetBlendEnabled(1, true)
|
|
context:GetShader(0):GetRenderStatesOverride():SetDepthBias(-1)
|
|
context:GetShader(0):GetRenderStatesOverride():SetDepthBiasClamp(0.2)
|
|
context:GetShader(0):GetRenderStatesOverride():SetStencilWriteMask(0xF0)
|
|
else
|
|
context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPositionCount()
|
|
context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPosition(0)
|
|
context:GetShader(0):GetRenderStatesOverride():ClearCullMode()
|
|
context:GetShader(0):GetRenderStatesOverride():ClearBlendEnabled(1)
|
|
context:GetShader(0):GetRenderStatesOverride():ClearDepthBias()
|
|
context:GetShader(0):GetRenderStatesOverride():ClearDepthBiasClamp()
|
|
context:GetShader(0):GetRenderStatesOverride():ClearStencilWriteMask()
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
|
|
EXPECT_EQ(1, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositionsCount);
|
|
EXPECT_EQ(2, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_x);
|
|
EXPECT_EQ(4, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_y);
|
|
EXPECT_EQ(RHI::CullMode::None, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_rasterState.m_cullMode);
|
|
EXPECT_EQ(1, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_blendState.m_targets[1].m_enable);
|
|
EXPECT_EQ(-1, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_rasterState.m_depthBias);
|
|
EXPECT_FLOAT_EQ(0.2, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_rasterState.m_depthBiasClamp);
|
|
EXPECT_EQ(0xF0, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_depthStencilState.m_stencil.m_writeMask);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
|
|
EXPECT_EQ(RHI::RenderStates_InvalidUInt, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositionsCount);
|
|
EXPECT_EQ(RHI::Limits::Pipeline::MultiSampleCustomLocationGridSize, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_x);
|
|
EXPECT_EQ(RHI::Limits::Pipeline::MultiSampleCustomLocationGridSize, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_y);
|
|
EXPECT_EQ(RHI::CullMode::Invalid, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_rasterState.m_cullMode);
|
|
EXPECT_EQ(RHI::RenderStates_InvalidBool, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_blendState.m_targets[1].m_enable);
|
|
EXPECT_EQ(RHI::RenderStates_InvalidInt, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_rasterState.m_depthBias);
|
|
EXPECT_FLOAT_EQ(RHI::RenderStates_InvalidFloat, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_rasterState.m_depthBiasClamp);
|
|
EXPECT_EQ(RHI::RenderStates_InvalidUInt, testData.GetMaterial()->GetShaderCollection()[0].GetRenderStatesOverlay()->m_depthStencilState.m_stencil.m_writeMask);
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderEnabledByTag)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.MyBool"}
|
|
end
|
|
|
|
function Process(context)
|
|
local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
|
|
context:GetShaderByTag("TestShader"):SetEnabled(boolValue)
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
|
|
EXPECT_EQ(true, testData.GetMaterial()->GetShaderCollection()[Name{"TestShader"}].IsEnabled());
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderDrawListTagOverride)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
RHI::DrawListTagRegistry* drawListTagRegistry = RHI::RHISystemInterface::Get()->GetDrawListTagRegistry();
|
|
drawListTagRegistry->AcquireTag(Name{"TestDrawListTag"});
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.MyBool"}
|
|
end
|
|
|
|
function Process(context)
|
|
context:GetShaderByTag("TestShader"):SetDrawListTagOverride("TestDrawListTag")
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
|
|
RHI::DrawListTag tag = drawListTagRegistry->FindTag(Name{"TestDrawListTag"});
|
|
EXPECT_EQ(tag, testData.GetMaterial()->GetShaderCollection()[Name{"TestShader"}].GetDrawListTagOverride());
|
|
|
|
drawListTagRegistry->ReleaseTag(tag);
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_PsoChangesNotAllowed_Error)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.MyBool"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {}
|
|
end
|
|
|
|
function Process(context)
|
|
local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
|
|
if(boolValue) then
|
|
context:GetShader(0):GetRenderStatesOverride():SetFillMode(FillMode_Wireframe)
|
|
else
|
|
context:GetShader(0):GetRenderStatesOverride():ClearFillMode()
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
|
|
ErrorMessageFinder errorMessageFinder;
|
|
|
|
errorMessageFinder.AddExpectedErrorMessage("not be changed at runtime because they impact Pipeline State Objects: general.MyBool");
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
errorMessageFinder.CheckExpectedErrorsFound();
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_MultisampleCustomPositionCountIndex_Error)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.MyBool"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {}
|
|
end
|
|
|
|
function Process(context)
|
|
local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
|
|
if(boolValue) then
|
|
context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPositionCount(20)
|
|
else
|
|
context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPositionCount()
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
|
|
|
|
testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed);
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
|
|
ErrorMessageFinder errorMessageFinder;
|
|
|
|
errorMessageFinder.AddExpectedErrorMessage("SetMultisampleCustomPositionCount(20) value is out of range. Must be less than 16.");
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
errorMessageFinder.CheckExpectedErrorsFound();
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_MultisampleCustomPositionIndex_Error)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.MyBool"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {}
|
|
end
|
|
|
|
function Process(context)
|
|
local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
|
|
if(boolValue) then
|
|
context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPosition(17, 0, 0)
|
|
else
|
|
context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPosition(18)
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
|
|
ErrorMessageFinder errorMessageFinder;
|
|
|
|
errorMessageFinder.AddExpectedErrorMessage("ClearMultisampleCustomPosition(18,...) index is out of range. Must be less than 16.");
|
|
testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
|
|
errorMessageFinder.CheckExpectedErrorsFound();
|
|
|
|
testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed);
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
|
|
errorMessageFinder.AddExpectedErrorMessage("SetMultisampleCustomPosition(17,...) index is out of range. Must be less than 16.");
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
errorMessageFinder.CheckExpectedErrorsFound();
|
|
}
|
|
|
|
TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_BlendStateIndex_Error)
|
|
{
|
|
using namespace AZ::RPI;
|
|
|
|
const char* functorScript =
|
|
R"(
|
|
function GetMaterialPropertyDependencies()
|
|
return {"general.MyBool"}
|
|
end
|
|
|
|
function GetShaderOptionDependencies()
|
|
return {}
|
|
end
|
|
|
|
function Process(context)
|
|
local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
|
|
if(boolValue) then
|
|
context:GetShader(0):GetRenderStatesOverride():SetBlendEnabled(9, false)
|
|
else
|
|
context:GetShader(0):GetRenderStatesOverride():ClearBlendEnabled(10)
|
|
end
|
|
end
|
|
)";
|
|
|
|
TestMaterialData testData;
|
|
|
|
ErrorMessageFinder errorMessageFinder;
|
|
|
|
errorMessageFinder.AddExpectedErrorMessage("ClearBlendEnabled(10,...) index is out of range. Must be less than 8.");
|
|
testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
|
|
errorMessageFinder.CheckExpectedErrorsFound();
|
|
|
|
testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed);
|
|
testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
|
|
|
|
errorMessageFinder.AddExpectedErrorMessage("SetBlendEnabled(9,...) index is out of range. Must be less than 8.");
|
|
EXPECT_TRUE(testData.GetMaterial()->Compile());
|
|
errorMessageFinder.CheckExpectedErrorsFound();
|
|
}
|
|
}
|