3
0

LuaMaterialFunctorTests.cpp 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzTest/AzTest.h>
  9. #include <Common/RPITestFixture.h>
  10. #include <Common/JsonTestUtils.h>
  11. #include <Common/ErrorMessageFinder.h>
  12. #include <Common/ShaderAssetTestUtils.h>
  13. #include <AzCore/Script/ScriptAsset.h>
  14. #include <Atom/RPI.Edit/Material/LuaMaterialFunctorSourceData.h>
  15. #include <Atom/RPI.Reflect/Material/LuaMaterialFunctor.h>
  16. #include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
  17. #include <Atom/RPI.Reflect/Material/MaterialTypeAssetCreator.h>
  18. #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
  19. #include <Atom/RPI.Reflect/Material/MaterialAssetCreator.h>
  20. #include <Atom/RPI.Public/Material/Material.h>
  21. #include <Material/MaterialAssetTestUtils.h>
  22. namespace UnitTest
  23. {
  24. using namespace AZ;
  25. using namespace RPI;
  26. class LuaMaterialFunctorTests
  27. : public RPITestFixture
  28. {
  29. public:
  30. static void AddLuaFunctor(MaterialTypeAssetCreator& materialTypeCreator, const AZStd::string& script, Name materialPipelineName = MaterialPipelineNone)
  31. {
  32. // See also MaterialTypeSourceData::AddFunctors
  33. LuaMaterialFunctorSourceData functorSourceData;
  34. functorSourceData.m_luaScript = script;
  35. MaterialNameContext nameContext;
  36. MaterialFunctorSourceData::RuntimeContext createFunctorContext{
  37. "Dummy.materialtype",
  38. materialTypeCreator.GetMaterialPropertiesLayout(materialPipelineName),
  39. (materialPipelineName == MaterialPipelineNone) ? materialTypeCreator.GetMaterialShaderResourceGroupLayout() : nullptr,
  40. &nameContext
  41. };
  42. MaterialFunctorSourceData::FunctorResult result = functorSourceData.CreateFunctor(createFunctorContext);
  43. EXPECT_TRUE(result.IsSuccess());
  44. if (result.IsSuccess())
  45. {
  46. materialTypeCreator.AddMaterialFunctor(result.GetValue(), materialPipelineName);
  47. for (auto& shaderOption : functorSourceData.GetShaderOptionDependencies())
  48. {
  49. materialTypeCreator.ClaimShaderOptionOwnership(shaderOption);
  50. }
  51. }
  52. }
  53. protected:
  54. void SetUp() override
  55. {
  56. RPITestFixture::SetUp();
  57. }
  58. void TearDown() override
  59. {
  60. RPITestFixture::TearDown();
  61. }
  62. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> CreateCommonTestShaderOptionsLayout()
  63. {
  64. AZStd::vector<RPI::ShaderOptionValuePair> boolOptionValues = CreateBoolShaderOptionValues();
  65. AZStd::vector<RPI::ShaderOptionValuePair> intRangeOptionValues = CreateIntRangeShaderOptionValues(0, 15);
  66. AZStd::vector<RPI::ShaderOptionValuePair> qualityOptionValues = CreateEnumShaderOptionValues({"Quality::Low", "Quality::Medium", "Quality::High"});
  67. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> shaderOptions = RPI::ShaderOptionGroupLayout::Create();
  68. shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_bool"}, ShaderOptionType::Boolean, 0, 0, boolOptionValues, Name{"False"}});
  69. shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_uint"}, ShaderOptionType::IntegerRange, 1, 1, intRangeOptionValues, Name{"0"}});
  70. shaderOptions->AddShaderOption(ShaderOptionDescriptor{Name{"o_enum"}, ShaderOptionType::Enumeration, 5, 2, qualityOptionValues, Name{"Quality::Low"}});
  71. shaderOptions->Finalize();
  72. return shaderOptions;
  73. }
  74. };
  75. class TestMaterialData
  76. {
  77. public:
  78. // Setup for a single material property and nothing else, used in particular to test setting render states
  79. void Setup(
  80. MaterialPropertyDataType dataType,
  81. const char* materialPropertyName,
  82. const char* luaFunctorScript)
  83. {
  84. MaterialTypeAssetCreator materialTypeCreator;
  85. materialTypeCreator.Begin(Uuid::CreateRandom());
  86. materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()), AZ::RPI::ShaderVariantId{}, Name{"TestShader"});
  87. materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
  88. materialTypeCreator.EndMaterialProperty();
  89. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
  90. EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
  91. Data::Asset<MaterialAsset> materialAsset;
  92. MaterialAssetCreator materialCreator;
  93. materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset);
  94. EXPECT_TRUE(materialCreator.End(materialAsset));
  95. m_material = Material::Create(materialAsset);
  96. m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
  97. }
  98. // Setup for a single material property and a specific shader constant input
  99. void Setup(
  100. RHI::Ptr<RHI::ShaderResourceGroupLayout> materialSrgLayout,
  101. MaterialPropertyDataType dataType,
  102. const char* materialPropertyName,
  103. const char* shaderInputName,
  104. const char* luaFunctorScript)
  105. {
  106. MaterialTypeAssetCreator materialTypeCreator;
  107. materialTypeCreator.Begin(Uuid::CreateRandom());
  108. materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout));
  109. materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
  110. materialTypeCreator.EndMaterialProperty();
  111. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
  112. EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
  113. Data::Asset<MaterialAsset> materialAsset;
  114. MaterialAssetCreator materialCreator;
  115. materialCreator.Begin(Uuid::CreateRandom(),m_materialTypeAsset);
  116. EXPECT_TRUE(materialCreator.End(materialAsset));
  117. m_material = Material::Create(materialAsset);
  118. m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
  119. m_srgConstantIndex = m_material->GetRHIShaderResourceGroup()->GetData().FindShaderInputConstantIndex(Name{shaderInputName});
  120. }
  121. // Setup for a single material property and a specific shader option
  122. void Setup(
  123. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> shaderOptionsLayout,
  124. MaterialPropertyDataType dataType,
  125. const char* materialPropertyName,
  126. const char* shaderOptionName,
  127. const char* luaFunctorScript)
  128. {
  129. MaterialTypeAssetCreator materialTypeCreator;
  130. materialTypeCreator.Begin(Uuid::CreateRandom());
  131. materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom(), {}, shaderOptionsLayout), AZ::RPI::ShaderVariantId{}, Name{"TestShader"});
  132. materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
  133. materialTypeCreator.EndMaterialProperty();
  134. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
  135. EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
  136. Data::Asset<MaterialAsset> materialAsset;
  137. MaterialAssetCreator materialCreator;
  138. materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset);
  139. EXPECT_TRUE(materialCreator.End(materialAsset));
  140. m_material = Material::Create(materialAsset);
  141. m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
  142. m_shaderOptionIndex = shaderOptionsLayout->FindShaderOptionIndex(Name{shaderOptionName});
  143. }
  144. // Setup for two material properties for testing one property affecting another property's metadata
  145. void Setup(
  146. MaterialPropertyDataType primaryPropertyDataType,
  147. const char* primaryPropertyName,
  148. MaterialPropertyDataType secondaryPropertyDataType,
  149. const char* secondaryPropertyName,
  150. const char* luaFunctorScript)
  151. {
  152. MaterialTypeAssetCreator materialTypeCreator;
  153. materialTypeCreator.Begin(Uuid::CreateRandom());
  154. materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()));
  155. materialTypeCreator.BeginMaterialProperty(Name{primaryPropertyName}, primaryPropertyDataType);
  156. materialTypeCreator.EndMaterialProperty();
  157. materialTypeCreator.BeginMaterialProperty(Name{secondaryPropertyName}, secondaryPropertyDataType);
  158. materialTypeCreator.EndMaterialProperty();
  159. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
  160. EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
  161. Data::Asset<MaterialAsset> materialAsset;
  162. MaterialAssetCreator materialCreator;
  163. materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset);
  164. EXPECT_TRUE(materialCreator.End(materialAsset));
  165. m_material = Material::Create(materialAsset);
  166. m_materialPropertyIndex = m_material->FindPropertyIndex(Name{primaryPropertyName});
  167. m_otherMaterialPropertyIndex = m_material->FindPropertyIndex(Name{secondaryPropertyName});
  168. }
  169. // Setup for a single material property connected to a material pipeline property, with a material pipeline functor
  170. void SetupMaterialPipeline(
  171. MaterialPropertyDataType dataType,
  172. const char* materialPropertyName,
  173. const char* pipelineMaterialPropertyName,
  174. const char* luaFunctorScriptForMaterialPipeline)
  175. {
  176. Name materialPipelineName{"TestPipeline"};
  177. MaterialTypeAssetCreator materialTypeCreator;
  178. materialTypeCreator.Begin(Uuid::CreateRandom());
  179. materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()), AZ::RPI::ShaderVariantId{}, Name{"TestShader"}, materialPipelineName);
  180. materialTypeCreator.BeginMaterialProperty(Name{pipelineMaterialPropertyName}, dataType, materialPipelineName);
  181. materialTypeCreator.EndMaterialProperty();
  182. materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
  183. materialTypeCreator.ConnectMaterialPropertyToInternalProperty(Name{pipelineMaterialPropertyName});
  184. materialTypeCreator.EndMaterialProperty();
  185. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScriptForMaterialPipeline, materialPipelineName);
  186. EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
  187. Data::Asset<MaterialAsset> materialAsset;
  188. MaterialAssetCreator materialCreator;
  189. materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset);
  190. EXPECT_TRUE(materialCreator.End(materialAsset));
  191. m_material = Material::Create(materialAsset);
  192. m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
  193. }
  194. // Setup for a single material property connected to a material pipeline property, with a material pipeline functor, including a shader option
  195. void SetupMaterialPipeline(
  196. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> shaderOptionsLayout,
  197. MaterialPropertyDataType dataType,
  198. const char* materialPropertyName,
  199. const char* pipelineMaterialPropertyName,
  200. const char* shaderOptionName,
  201. const char* luaFunctorScriptForMaterialPipeline)
  202. {
  203. Name materialPipelineName{"TestPipeline"};
  204. MaterialTypeAssetCreator materialTypeCreator;
  205. materialTypeCreator.Begin(Uuid::CreateRandom());
  206. materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom(), {}, shaderOptionsLayout), AZ::RPI::ShaderVariantId{}, Name{"TestShader"}, materialPipelineName);
  207. materialTypeCreator.BeginMaterialProperty(Name{pipelineMaterialPropertyName}, dataType, materialPipelineName);
  208. materialTypeCreator.EndMaterialProperty();
  209. materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, dataType);
  210. materialTypeCreator.ConnectMaterialPropertyToInternalProperty(Name{pipelineMaterialPropertyName});
  211. materialTypeCreator.EndMaterialProperty();
  212. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScriptForMaterialPipeline, materialPipelineName);
  213. EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
  214. Data::Asset<MaterialAsset> materialAsset;
  215. MaterialAssetCreator materialCreator;
  216. materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset);
  217. EXPECT_TRUE(materialCreator.End(materialAsset));
  218. m_material = Material::Create(materialAsset);
  219. m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
  220. m_shaderOptionIndex = shaderOptionsLayout->FindShaderOptionIndex(Name{shaderOptionName});
  221. }
  222. // Setup for a single material property with a material functor, and a material pipeline property with a material pipeline functor
  223. void SetupMaterialPipeline(
  224. MaterialPropertyDataType materialPropertyType,
  225. const char* materialPropertyName,
  226. const char* luaFunctorScript,
  227. MaterialPropertyDataType pipelineMaterialPropertyType,
  228. const char* pipelineMaterialPropertyName,
  229. const char* luaFunctorScriptForMaterialPipeline)
  230. {
  231. Name materialPipelineName{"TestPipeline"};
  232. MaterialTypeAssetCreator materialTypeCreator;
  233. materialTypeCreator.Begin(Uuid::CreateRandom());
  234. materialTypeCreator.AddShader(CreateTestShaderAsset(Uuid::CreateRandom()), AZ::RPI::ShaderVariantId{}, Name{"TestShader"}, materialPipelineName);
  235. materialTypeCreator.BeginMaterialProperty(Name{pipelineMaterialPropertyName}, pipelineMaterialPropertyType, materialPipelineName);
  236. materialTypeCreator.EndMaterialProperty();
  237. materialTypeCreator.BeginMaterialProperty(Name{materialPropertyName}, materialPropertyType);
  238. materialTypeCreator.ConnectMaterialPropertyToInternalProperty(Name{pipelineMaterialPropertyName});
  239. materialTypeCreator.EndMaterialProperty();
  240. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScript);
  241. LuaMaterialFunctorTests::AddLuaFunctor(materialTypeCreator, luaFunctorScriptForMaterialPipeline, materialPipelineName);
  242. EXPECT_TRUE(materialTypeCreator.End(m_materialTypeAsset));
  243. Data::Asset<MaterialAsset> materialAsset;
  244. MaterialAssetCreator materialCreator;
  245. materialCreator.Begin(Uuid::CreateRandom(), m_materialTypeAsset);
  246. EXPECT_TRUE(materialCreator.End(materialAsset));
  247. m_material = Material::Create(materialAsset);
  248. m_materialPropertyIndex = m_material->FindPropertyIndex(Name{materialPropertyName});
  249. }
  250. Data::Asset<MaterialTypeAsset> GetMaterialTypeAsset() { return m_materialTypeAsset; }
  251. Data::Instance<Material> GetMaterial() { return m_material; }
  252. MaterialPropertyIndex GetMaterialPropertyIndex() { return m_materialPropertyIndex; }
  253. MaterialPropertyIndex GetOtherMaterialPropertyIndex() { return m_otherMaterialPropertyIndex; }
  254. RHI::ShaderInputConstantIndex GetSrgConstantIndex() { return m_srgConstantIndex; }
  255. ShaderOptionIndex GetShaderOptionIndex() { return m_shaderOptionIndex; }
  256. private:
  257. Data::Asset<MaterialTypeAsset> m_materialTypeAsset;
  258. Data::Instance<Material> m_material;
  259. MaterialPropertyIndex m_materialPropertyIndex;
  260. MaterialPropertyIndex m_otherMaterialPropertyIndex;
  261. RHI::ShaderInputConstantIndex m_srgConstantIndex;
  262. ShaderOptionIndex m_shaderOptionIndex;
  263. };
  264. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Bool)
  265. {
  266. using namespace AZ::RPI;
  267. const char* functorScript =
  268. R"(
  269. function GetMaterialPropertyDependencies()
  270. return {"general.TestBool"}
  271. end
  272. function Process(context)
  273. local value = context:GetMaterialPropertyValue_bool("general.TestBool")
  274. context:SetShaderConstant_bool("m_bool", value)
  275. end
  276. )";
  277. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  278. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  279. TestMaterialData testData;
  280. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Bool, "general.TestBool", "m_bool", functorScript);
  281. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  282. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  283. EXPECT_TRUE(testData.GetMaterial()->Compile());
  284. EXPECT_EQ(true, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<bool>(testData.GetSrgConstantIndex()));
  285. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  286. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  287. EXPECT_TRUE(testData.GetMaterial()->Compile());
  288. EXPECT_EQ(false, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<bool>(testData.GetSrgConstantIndex()));
  289. }
  290. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Float)
  291. {
  292. using namespace AZ::RPI;
  293. const char* functorScript =
  294. R"(
  295. function GetMaterialPropertyDependencies()
  296. return {"general.TestFloat"}
  297. end
  298. function Process(context)
  299. local value = context:GetMaterialPropertyValue_float("general.TestFloat")
  300. context:SetShaderConstant_float("m_float", value * 2.0)
  301. end
  302. )";
  303. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  304. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  305. TestMaterialData testData;
  306. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Float, "general.TestFloat", "m_float", functorScript);
  307. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1.25f});
  308. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  309. EXPECT_TRUE(testData.GetMaterial()->Compile());
  310. EXPECT_FLOAT_EQ(2.5f, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<float>(testData.GetSrgConstantIndex()));
  311. }
  312. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Int)
  313. {
  314. using namespace AZ::RPI;
  315. const char* functorScript =
  316. R"(
  317. function GetMaterialPropertyDependencies()
  318. return {"general.TestInt"}
  319. end
  320. function Process(context)
  321. local value = context:GetMaterialPropertyValue_int("general.TestInt")
  322. context:SetShaderConstant_int("m_int", value * -1)
  323. end
  324. )";
  325. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  326. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  327. TestMaterialData testData;
  328. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Int, "general.TestInt", "m_int", functorScript);
  329. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{2});
  330. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  331. EXPECT_TRUE(testData.GetMaterial()->Compile());
  332. EXPECT_EQ(-2, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<int32_t>(testData.GetSrgConstantIndex()));
  333. }
  334. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_UInt)
  335. {
  336. using namespace AZ::RPI;
  337. const char* functorScript =
  338. R"(
  339. function GetMaterialPropertyDependencies()
  340. return {"general.TestUInt"}
  341. end
  342. function Process(context)
  343. local value = context:GetMaterialPropertyValue_uint("general.TestUInt")
  344. context:SetShaderConstant_uint("m_uint", value + 5)
  345. end
  346. )";
  347. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  348. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  349. TestMaterialData testData;
  350. testData.Setup(materialSrgLayout, MaterialPropertyDataType::UInt, "general.TestUInt", "m_uint", functorScript);
  351. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{2u});
  352. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  353. EXPECT_TRUE(testData.GetMaterial()->Compile());
  354. EXPECT_EQ(7, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<uint32_t>(testData.GetSrgConstantIndex()));
  355. }
  356. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Float2)
  357. {
  358. using namespace AZ::RPI;
  359. const char* functorScript =
  360. R"(
  361. function GetMaterialPropertyDependencies()
  362. return {"general.TestVector2"}
  363. end
  364. function Process(context)
  365. local value = context:GetMaterialPropertyValue_Vector2("general.TestVector2")
  366. local swap = value.y
  367. value.y = value.x
  368. value.x = swap
  369. context:SetShaderConstant_Vector2("m_float2", value)
  370. end
  371. )";
  372. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  373. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  374. TestMaterialData testData;
  375. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector2, "general.TestVector2", "m_float2", functorScript);
  376. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector2(1.0f, 2.0f)});
  377. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  378. EXPECT_TRUE(testData.GetMaterial()->Compile());
  379. EXPECT_EQ(Vector2(2.0f, 1.0f), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Vector2>(testData.GetSrgConstantIndex()));
  380. }
  381. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Vector3)
  382. {
  383. using namespace AZ::RPI;
  384. const char* functorScript =
  385. R"(
  386. function GetMaterialPropertyDependencies()
  387. return {"general.TestVector3"}
  388. end
  389. function Process(context)
  390. local value = context:GetMaterialPropertyValue_Vector3("general.TestVector3")
  391. value:Normalize()
  392. context:SetShaderConstant_Vector3("m_float3", value)
  393. end
  394. )";
  395. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  396. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  397. TestMaterialData testData;
  398. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector3, "general.TestVector3", "m_float3", functorScript);
  399. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector3(5.0f, 4.0f, 3.0f)});
  400. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  401. EXPECT_TRUE(testData.GetMaterial()->Compile());
  402. EXPECT_EQ(Vector3(5.0f, 4.0f, 3.0f).GetNormalized(), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Vector3>(testData.GetSrgConstantIndex()));
  403. }
  404. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Vector4)
  405. {
  406. using namespace AZ::RPI;
  407. const char* functorScript =
  408. R"(
  409. function GetMaterialPropertyDependencies()
  410. return {"general.TestVector4"}
  411. end
  412. function Process(context)
  413. local value = context:GetMaterialPropertyValue_Vector4("general.TestVector4")
  414. value:Homogenize()
  415. context:SetShaderConstant_Vector4("m_float4", value)
  416. end
  417. )";
  418. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  419. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  420. TestMaterialData testData;
  421. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector4, "general.TestVector4", "m_float4", functorScript);
  422. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector4(1.0f, 2.0f, 3.0f, 4.0f)});
  423. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  424. EXPECT_TRUE(testData.GetMaterial()->Compile());
  425. EXPECT_EQ(Vector4(1.0f, 2.0f, 3.0f, 4.0f) / 4.0f, testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Vector4>(testData.GetSrgConstantIndex()));
  426. }
  427. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetShaderConstant_Color)
  428. {
  429. using namespace AZ::RPI;
  430. const char* functorScript =
  431. R"(
  432. function GetMaterialPropertyDependencies()
  433. return {"general.TestColor"}
  434. end
  435. function Process(context)
  436. local value = context:GetMaterialPropertyValue_Color("general.TestColor")
  437. value.r = value.r * value.a
  438. value.g = value.g * value.a
  439. value.b = value.b * value.a
  440. context:SetShaderConstant_Color("m_color", value)
  441. end
  442. )";
  443. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  444. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  445. TestMaterialData testData;
  446. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Color, "general.TestColor", "m_color", functorScript);
  447. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Color(1.0f, 0.5f, 0.4f, 0.5f)});
  448. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  449. EXPECT_TRUE(testData.GetMaterial()->Compile());
  450. EXPECT_EQ(Color(0.5f, 0.25f, 0.2f, 0.5f), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Color>(testData.GetSrgConstantIndex()));
  451. }
  452. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderConstant_Matrix3x3)
  453. {
  454. using namespace AZ::RPI;
  455. const char* functorScript =
  456. R"(
  457. function GetMaterialPropertyDependencies()
  458. return {"general.Scale"}
  459. end
  460. function Process(context)
  461. local scale = context:GetMaterialPropertyValue_float("general.Scale")
  462. local tansform = Matrix3x3.CreateScale(Vector3(scale, scale, 1.0))
  463. context:SetShaderConstant_Matrix3x3("m_float3x3", tansform)
  464. end
  465. )";
  466. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  467. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  468. TestMaterialData testData;
  469. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Float, "general.Scale", "m_float3x3", functorScript);
  470. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0.5f});
  471. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  472. EXPECT_TRUE(testData.GetMaterial()->Compile());
  473. EXPECT_EQ(Matrix3x3::CreateScale(Vector3(0.5f, 0.5f, 1.0f)), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Matrix3x3>(testData.GetSrgConstantIndex()));
  474. }
  475. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderConstant_Matrix4x4)
  476. {
  477. using namespace AZ::RPI;
  478. const char* functorScript =
  479. R"(
  480. function GetMaterialPropertyDependencies()
  481. return {"general.Offset"}
  482. end
  483. function Process(context)
  484. local offset = context:GetMaterialPropertyValue_Vector3("general.Offset")
  485. local tansform = Matrix4x4.CreateTranslation(offset)
  486. context:SetShaderConstant_Matrix4x4("m_float4x4", tansform)
  487. end
  488. )";
  489. auto materialSrgLayout = CreateCommonTestMaterialSrgLayout();
  490. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), materialSrgLayout);
  491. TestMaterialData testData;
  492. testData.Setup(materialSrgLayout, MaterialPropertyDataType::Vector3, "general.Offset", "m_float4x4", functorScript);
  493. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{Vector3(1.0f, 2.0f, 3.0f)});
  494. ProcessQueuedSrgCompilations(shaderAsset, materialSrgLayout->GetName());
  495. EXPECT_TRUE(testData.GetMaterial()->Compile());
  496. EXPECT_EQ(Matrix4x4::CreateTranslation(Vector3(1.0f, 2.0f, 3.0f)), testData.GetMaterial()->GetRHIShaderResourceGroup()->GetData().GetConstant<Matrix4x4>(testData.GetSrgConstantIndex()));
  497. }
  498. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderOption_Bool)
  499. {
  500. using namespace AZ::RPI;
  501. const char* functorScript =
  502. R"(
  503. function GetMaterialPropertyDependencies()
  504. return {"general.TestBool"}
  505. end
  506. function GetShaderOptionDependencies()
  507. return {"o_bool"}
  508. end
  509. function Process(context)
  510. local value = context:GetMaterialPropertyValue_bool("general.TestBool")
  511. context:SetShaderOptionValue_bool("o_bool", value)
  512. end
  513. )";
  514. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  515. TestMaterialData testData;
  516. testData.Setup(options, MaterialPropertyDataType::Bool, "general.TestBool", "o_bool", functorScript);
  517. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  518. EXPECT_TRUE(testData.GetMaterial()->Compile());
  519. EXPECT_EQ(1, testData.GetMaterial()->GetGeneralShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
  520. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  521. EXPECT_TRUE(testData.GetMaterial()->Compile());
  522. EXPECT_EQ(0, testData.GetMaterial()->GetGeneralShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
  523. }
  524. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderOption_UInt)
  525. {
  526. using namespace AZ::RPI;
  527. const char* functorScript =
  528. R"(
  529. function GetMaterialPropertyDependencies()
  530. return {"general.TestInt"}
  531. end
  532. function GetShaderOptionDependencies()
  533. return {"o_uint"}
  534. end
  535. function Process(context)
  536. local value = context:GetMaterialPropertyValue_int("general.TestInt")
  537. context:SetShaderOptionValue_uint("o_uint", value * 2)
  538. end
  539. )";
  540. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  541. TestMaterialData testData;
  542. testData.Setup(options, MaterialPropertyDataType::Int, "general.TestInt", "o_uint", functorScript);
  543. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{6});
  544. EXPECT_TRUE(testData.GetMaterial()->Compile());
  545. EXPECT_EQ(12, testData.GetMaterial()->GetGeneralShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_uint"}).GetIndex());
  546. }
  547. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderOption_Enum)
  548. {
  549. using namespace AZ::RPI;
  550. const char* functorScript =
  551. R"(
  552. function GetMaterialPropertyDependencies()
  553. return {"general.UseHighQuality"}
  554. end
  555. function GetShaderOptionDependencies()
  556. return {"o_enum"}
  557. end
  558. function Process(context)
  559. local useHighQuality = context:GetMaterialPropertyValue_bool("general.UseHighQuality")
  560. if (useHighQuality) then
  561. context:SetShaderOptionValue_enum("o_enum", "Quality::High")
  562. else
  563. context:SetShaderOptionValue_enum("o_enum", "Quality::Medium")
  564. end
  565. end
  566. )";
  567. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  568. TestMaterialData testData;
  569. testData.Setup(options, MaterialPropertyDataType::Bool, "general.UseHighQuality", "o_enum", functorScript);
  570. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  571. EXPECT_TRUE(testData.GetMaterial()->Compile());
  572. EXPECT_EQ(2, testData.GetMaterial()->GetGeneralShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
  573. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  574. EXPECT_TRUE(testData.GetMaterial()->Compile());
  575. EXPECT_EQ(1, testData.GetMaterial()->GetGeneralShaderCollection()[0].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
  576. }
  577. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_ShaderItem_SetShaderOption_Bool)
  578. {
  579. using namespace AZ::RPI;
  580. const char* functorScript =
  581. R"(
  582. function GetMaterialPropertyDependencies()
  583. return {"general.TestBool"}
  584. end
  585. function GetShaderOptionDependencies()
  586. return {"o_bool"}
  587. end
  588. function Process(context)
  589. local value = context:GetMaterialPropertyValue_bool("general.TestBool")
  590. context:GetShaderByTag("TestShader"):SetShaderOptionValue_bool("o_bool", value)
  591. end
  592. )";
  593. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  594. TestMaterialData testData;
  595. testData.Setup(options, MaterialPropertyDataType::Bool, "general.TestBool", "o_bool", functorScript);
  596. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  597. EXPECT_TRUE(testData.GetMaterial()->Compile());
  598. EXPECT_EQ(
  599. 1, testData.GetMaterial()->GetGeneralShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
  600. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  601. EXPECT_TRUE(testData.GetMaterial()->Compile());
  602. EXPECT_EQ(
  603. 0, testData.GetMaterial()->GetGeneralShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
  604. }
  605. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_ShaderItem_SetShaderOption_UInt)
  606. {
  607. using namespace AZ::RPI;
  608. const char* functorScript =
  609. R"(
  610. function GetMaterialPropertyDependencies()
  611. return {"general.TestInt"}
  612. end
  613. function GetShaderOptionDependencies()
  614. return {"o_uint"}
  615. end
  616. function Process(context)
  617. local value = context:GetMaterialPropertyValue_int("general.TestInt")
  618. context:GetShaderByTag("TestShader"):SetShaderOptionValue_uint("o_uint", value * 2)
  619. end
  620. )";
  621. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  622. TestMaterialData testData;
  623. testData.Setup(options, MaterialPropertyDataType::Int, "general.TestInt", "o_uint", functorScript);
  624. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{6});
  625. EXPECT_TRUE(testData.GetMaterial()->Compile());
  626. EXPECT_EQ(
  627. 12, testData.GetMaterial()->GetGeneralShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_uint"}).GetIndex());
  628. }
  629. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_ShaderItem_SetShaderOption_Enum)
  630. {
  631. using namespace AZ::RPI;
  632. const char* functorScript =
  633. R"(
  634. function GetMaterialPropertyDependencies()
  635. return {"general.UseHighQuality"}
  636. end
  637. function GetShaderOptionDependencies()
  638. return {"o_enum"}
  639. end
  640. function Process(context)
  641. local useHighQuality = context:GetMaterialPropertyValue_bool("general.UseHighQuality")
  642. if (useHighQuality) then
  643. context:GetShaderByTag("TestShader"):SetShaderOptionValue_enum("o_enum", "Quality::High")
  644. else
  645. context:GetShaderByTag("TestShader"):SetShaderOptionValue_enum("o_enum", "Quality::Medium")
  646. end
  647. end
  648. )";
  649. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  650. TestMaterialData testData;
  651. testData.Setup(options, MaterialPropertyDataType::Bool, "general.UseHighQuality", "o_enum", functorScript);
  652. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  653. EXPECT_TRUE(testData.GetMaterial()->Compile());
  654. EXPECT_EQ(
  655. 2, testData.GetMaterial()->GetGeneralShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
  656. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  657. EXPECT_TRUE(testData.GetMaterial()->Compile());
  658. EXPECT_EQ(
  659. 1, testData.GetMaterial()->GetGeneralShaderCollection()[Name{"TestShader"}].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
  660. }
  661. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_EditorContext_SetMaterialPropertyVisibility)
  662. {
  663. using namespace AZ::RPI;
  664. const char* functorScript =
  665. R"(
  666. function GetMaterialPropertyDependencies()
  667. return { "general.mode" }
  668. end
  669. function ProcessEditor(context)
  670. local mode = context:GetMaterialPropertyValue_uint("general.mode")
  671. if (mode == 1) then
  672. context:SetMaterialPropertyVisibility("general.value", MaterialPropertyVisibility_Enabled)
  673. elseif (mode == 2) then
  674. context:SetMaterialPropertyVisibility("general.value", MaterialPropertyVisibility_Disabled)
  675. else
  676. context:SetMaterialPropertyVisibility("general.value", MaterialPropertyVisibility_Hidden)
  677. end
  678. end
  679. )";
  680. TestMaterialData testData;
  681. testData.Setup(
  682. MaterialPropertyDataType::UInt, "general.mode",
  683. MaterialPropertyDataType::Float, "general.value",
  684. functorScript);
  685. AZStd::unordered_set<AZ::Name> changedPropertyNames;
  686. AZStd::unordered_map<Name, MaterialPropertyDynamicMetadata> propertyDynamicMetadata;
  687. propertyDynamicMetadata[Name{"general.mode"}] = {};
  688. propertyDynamicMetadata[Name{"general.value"}] = {};
  689. AZStd::unordered_set<AZ::Name> changedPropertyGroupNames;
  690. AZStd::unordered_map<Name, MaterialPropertyGroupDynamicMetadata> propertyGroupDynamicMetadata;
  691. propertyGroupDynamicMetadata[Name{"general"}] = {};
  692. Ptr<MaterialFunctor> functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0];
  693. AZ::RPI::MaterialFunctorAPI::EditorContext context = AZ::RPI::MaterialFunctorAPI::EditorContext(
  694. testData.GetMaterial()->GetPropertyCollection(),
  695. propertyDynamicMetadata,
  696. propertyGroupDynamicMetadata,
  697. changedPropertyNames,
  698. changedPropertyGroupNames,
  699. &functor->GetMaterialPropertyDependencies()
  700. );
  701. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u});
  702. functor->Process(context);
  703. EXPECT_EQ(MaterialPropertyVisibility::Hidden, propertyDynamicMetadata[Name{"general.value"}].m_visibility);
  704. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u});
  705. functor->Process(context);
  706. EXPECT_EQ(MaterialPropertyVisibility::Enabled, propertyDynamicMetadata[Name{"general.value"}].m_visibility);
  707. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{2u});
  708. functor->Process(context);
  709. EXPECT_EQ(MaterialPropertyVisibility::Disabled, propertyDynamicMetadata[Name{"general.value"}].m_visibility);
  710. }
  711. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_EditorContext_SetMaterialPropertyDescriptionAndRanges)
  712. {
  713. using namespace AZ::RPI;
  714. const char* functorScript =
  715. R"(
  716. function GetMaterialPropertyDependencies()
  717. return { "general.units" }
  718. end
  719. function ProcessEditor(context)
  720. local units = context:GetMaterialPropertyValue_uint("general.units")
  721. if (units == 0) then
  722. context:SetMaterialPropertyDescription("general.distance", "Distance in meters")
  723. context:SetMaterialPropertyMinValue_float("general.distance", -10)
  724. context:SetMaterialPropertyMaxValue_float("general.distance", 10)
  725. context:SetMaterialPropertySoftMinValue_float("general.distance", -1)
  726. context:SetMaterialPropertySoftMaxValue_float("general.distance", 1)
  727. else
  728. context:SetMaterialPropertyDescription("general.distance", "Distance in centimeters")
  729. context:SetMaterialPropertyMinValue_float("general.distance", -1000)
  730. context:SetMaterialPropertyMaxValue_float("general.distance", 1000)
  731. context:SetMaterialPropertySoftMinValue_float("general.distance", -100)
  732. context:SetMaterialPropertySoftMaxValue_float("general.distance", 100)
  733. end
  734. end
  735. )";
  736. TestMaterialData testData;
  737. testData.Setup(
  738. MaterialPropertyDataType::UInt, "general.units",
  739. MaterialPropertyDataType::Float, "general.distance",
  740. functorScript);
  741. AZStd::unordered_set<AZ::Name> changedPropertyNames;
  742. AZStd::unordered_map<Name, MaterialPropertyDynamicMetadata> propertyDynamicMetadata;
  743. propertyDynamicMetadata[Name{"general.units"}] = {};
  744. propertyDynamicMetadata[Name{"general.distance"}] = {};
  745. AZStd::unordered_set<AZ::Name> changedPropertyGroupNames;
  746. AZStd::unordered_map<Name, MaterialPropertyGroupDynamicMetadata> propertyGroupDynamicMetadata;
  747. propertyGroupDynamicMetadata[Name{"general"}] = {};
  748. Ptr<MaterialFunctor> functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0];
  749. AZ::RPI::MaterialFunctorAPI::EditorContext context = AZ::RPI::MaterialFunctorAPI::EditorContext(
  750. testData.GetMaterial()->GetPropertyCollection(),
  751. propertyDynamicMetadata,
  752. propertyGroupDynamicMetadata,
  753. changedPropertyNames,
  754. changedPropertyGroupNames,
  755. &functor->GetMaterialPropertyDependencies()
  756. );
  757. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u});
  758. functor->Process(context);
  759. EXPECT_STREQ("Distance in meters", propertyDynamicMetadata[Name{"general.distance"}].m_description.c_str());
  760. EXPECT_EQ(-10.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_min.GetValue<float>());
  761. EXPECT_EQ(10.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_max.GetValue<float>());
  762. EXPECT_EQ(-1.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMin.GetValue<float>());
  763. EXPECT_EQ(1.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMax.GetValue<float>());
  764. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u});
  765. functor->Process(context);
  766. EXPECT_STREQ("Distance in centimeters", propertyDynamicMetadata[Name{"general.distance"}].m_description.c_str());
  767. EXPECT_EQ(-1000.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_min.GetValue<float>());
  768. EXPECT_EQ(1000.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_max.GetValue<float>());
  769. EXPECT_EQ(-100.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMin.GetValue<float>());
  770. EXPECT_EQ(100.0f, propertyDynamicMetadata[Name{"general.distance"}].m_propertyRange.m_softMax.GetValue<float>());
  771. }
  772. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_EditorContext_SetMaterialPropertyGroupVisibility)
  773. {
  774. using namespace AZ::RPI;
  775. const char* functorScript =
  776. R"(
  777. function GetMaterialPropertyDependencies()
  778. return { "general.mode" }
  779. end
  780. function ProcessEditor(context)
  781. local mode = context:GetMaterialPropertyValue_uint("general.mode")
  782. if (mode == 1) then
  783. context:SetMaterialPropertyGroupVisibility("otherGroup", MaterialPropertyGroupVisibility_Enabled)
  784. else
  785. context:SetMaterialPropertyGroupVisibility("otherGroup", MaterialPropertyGroupVisibility_Hidden)
  786. end
  787. end
  788. )";
  789. TestMaterialData testData;
  790. testData.Setup(
  791. MaterialPropertyDataType::UInt, "general.mode",
  792. MaterialPropertyDataType::Float, "otherGroup.value",
  793. functorScript);
  794. AZStd::unordered_set<AZ::Name> changedPropertyNames;
  795. AZStd::unordered_map<Name, MaterialPropertyDynamicMetadata> propertyDynamicMetadata;
  796. propertyDynamicMetadata[Name{"general.mode"}] = {};
  797. propertyDynamicMetadata[Name{"otherGroup.value"}] = {};
  798. AZStd::unordered_set<AZ::Name> changedPropertyGroupNames;
  799. AZStd::unordered_map<Name, MaterialPropertyGroupDynamicMetadata> propertyGroupDynamicMetadata;
  800. propertyGroupDynamicMetadata[Name{"general"}] = {};
  801. propertyGroupDynamicMetadata[Name{"otherGroup"}] = {};
  802. Ptr<MaterialFunctor> functor = testData.GetMaterialTypeAsset()->GetMaterialFunctors()[0];
  803. AZ::RPI::MaterialFunctorAPI::EditorContext context = AZ::RPI::MaterialFunctorAPI::EditorContext(
  804. testData.GetMaterial()->GetPropertyCollection(),
  805. propertyDynamicMetadata,
  806. propertyGroupDynamicMetadata,
  807. changedPropertyNames,
  808. changedPropertyGroupNames,
  809. &functor->GetMaterialPropertyDependencies()
  810. );
  811. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u});
  812. functor->Process(context);
  813. EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"general"}].m_visibility);
  814. EXPECT_EQ(MaterialPropertyGroupVisibility::Hidden, propertyGroupDynamicMetadata[Name{"otherGroup"}].m_visibility);
  815. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u});
  816. functor->Process(context);
  817. EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"general"}].m_visibility);
  818. EXPECT_EQ(MaterialPropertyGroupVisibility::Enabled, propertyGroupDynamicMetadata[Name{"otherGroup"}].m_visibility);
  819. }
  820. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetRenderStates)
  821. {
  822. using namespace AZ::RPI;
  823. // We aren't testing every single render state here, but just getting a representative set...
  824. const char* functorScript =
  825. R"(
  826. function GetMaterialPropertyDependencies()
  827. return {"general.MyBool"}
  828. end
  829. function Process(context)
  830. local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
  831. if(boolValue) then
  832. context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPositionCount(1)
  833. context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPosition(0, 2, 4)
  834. context:GetShader(0):GetRenderStatesOverride():SetCullMode(CullMode_None)
  835. context:GetShader(0):GetRenderStatesOverride():SetBlendEnabled(1, true)
  836. context:GetShader(0):GetRenderStatesOverride():SetDepthBias(-1)
  837. context:GetShader(0):GetRenderStatesOverride():SetDepthBiasClamp(0.2)
  838. context:GetShader(0):GetRenderStatesOverride():SetStencilWriteMask(0xF0)
  839. else
  840. context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPositionCount()
  841. context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPosition(0)
  842. context:GetShader(0):GetRenderStatesOverride():ClearCullMode()
  843. context:GetShader(0):GetRenderStatesOverride():ClearBlendEnabled(1)
  844. context:GetShader(0):GetRenderStatesOverride():ClearDepthBias()
  845. context:GetShader(0):GetRenderStatesOverride():ClearDepthBiasClamp()
  846. context:GetShader(0):GetRenderStatesOverride():ClearStencilWriteMask()
  847. end
  848. end
  849. )";
  850. TestMaterialData testData;
  851. testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
  852. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  853. EXPECT_TRUE(testData.GetMaterial()->Compile());
  854. const ShaderCollection& shaderCollection = testData.GetMaterial()->GetGeneralShaderCollection();
  855. EXPECT_EQ(1, shaderCollection[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositionsCount);
  856. EXPECT_EQ(2, shaderCollection[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_x);
  857. EXPECT_EQ(4, shaderCollection[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_y);
  858. EXPECT_EQ(RHI::CullMode::None, shaderCollection[0].GetRenderStatesOverlay()->m_rasterState.m_cullMode);
  859. EXPECT_EQ(1, shaderCollection[0].GetRenderStatesOverlay()->m_blendState.m_targets[1].m_enable);
  860. EXPECT_EQ(-1, shaderCollection[0].GetRenderStatesOverlay()->m_rasterState.m_depthBias);
  861. EXPECT_FLOAT_EQ(0.2, shaderCollection[0].GetRenderStatesOverlay()->m_rasterState.m_depthBiasClamp);
  862. EXPECT_EQ(0xF0, shaderCollection[0].GetRenderStatesOverlay()->m_depthStencilState.m_stencil.m_writeMask);
  863. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  864. EXPECT_TRUE(testData.GetMaterial()->Compile());
  865. EXPECT_EQ(RHI::RenderStates_InvalidUInt, shaderCollection[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositionsCount);
  866. EXPECT_EQ(RHI::Limits::Pipeline::MultiSampleCustomLocationGridSize, shaderCollection[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_x);
  867. EXPECT_EQ(RHI::Limits::Pipeline::MultiSampleCustomLocationGridSize, shaderCollection[0].GetRenderStatesOverlay()->m_multisampleState.m_customPositions[0].m_y);
  868. EXPECT_EQ(RHI::CullMode::Invalid, shaderCollection[0].GetRenderStatesOverlay()->m_rasterState.m_cullMode);
  869. EXPECT_EQ(RHI::RenderStates_InvalidBool, shaderCollection[0].GetRenderStatesOverlay()->m_blendState.m_targets[1].m_enable);
  870. EXPECT_EQ(RHI::RenderStates_InvalidInt, shaderCollection[0].GetRenderStatesOverlay()->m_rasterState.m_depthBias);
  871. EXPECT_FLOAT_EQ(RHI::RenderStates_InvalidFloat, shaderCollection[0].GetRenderStatesOverlay()->m_rasterState.m_depthBiasClamp);
  872. EXPECT_EQ(RHI::RenderStates_InvalidUInt, shaderCollection[0].GetRenderStatesOverlay()->m_depthStencilState.m_stencil.m_writeMask);
  873. }
  874. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderEnabledByTag)
  875. {
  876. using namespace AZ::RPI;
  877. const char* functorScript =
  878. R"(
  879. function GetMaterialPropertyDependencies()
  880. return {"general.MyBool"}
  881. end
  882. function Process(context)
  883. local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
  884. context:GetShaderByTag("TestShader"):SetEnabled(boolValue)
  885. end
  886. )";
  887. TestMaterialData testData;
  888. testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
  889. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  890. EXPECT_TRUE(testData.GetMaterial()->Compile());
  891. EXPECT_EQ(true, testData.GetMaterial()->GetGeneralShaderCollection()[Name{"TestShader"}].IsEnabled());
  892. }
  893. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetShaderDrawListTagOverride)
  894. {
  895. using namespace AZ::RPI;
  896. RHI::DrawListTagRegistry* drawListTagRegistry = RHI::RHISystemInterface::Get()->GetDrawListTagRegistry();
  897. drawListTagRegistry->AcquireTag(Name{"TestDrawListTag"});
  898. const char* functorScript =
  899. R"(
  900. function GetMaterialPropertyDependencies()
  901. return {"general.MyBool"}
  902. end
  903. function Process(context)
  904. context:GetShaderByTag("TestShader"):SetDrawListTagOverride("TestDrawListTag")
  905. end
  906. )";
  907. TestMaterialData testData;
  908. testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
  909. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  910. EXPECT_TRUE(testData.GetMaterial()->Compile());
  911. RHI::DrawListTag tag = drawListTagRegistry->FindTag(Name{"TestDrawListTag"});
  912. EXPECT_EQ(tag, testData.GetMaterial()->GetGeneralShaderCollection()[Name{"TestShader"}].GetDrawListTagOverride());
  913. drawListTagRegistry->ReleaseTag(tag);
  914. }
  915. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_PsoChangesNotAllowed_Error)
  916. {
  917. using namespace AZ::RPI;
  918. const char* functorScript =
  919. R"(
  920. function GetMaterialPropertyDependencies()
  921. return {"general.MyBool"}
  922. end
  923. function GetShaderOptionDependencies()
  924. return {}
  925. end
  926. function Process(context)
  927. local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
  928. if(boolValue) then
  929. context:GetShader(0):GetRenderStatesOverride():SetFillMode(FillMode_Wireframe)
  930. else
  931. context:GetShader(0):GetRenderStatesOverride():ClearFillMode()
  932. end
  933. end
  934. )";
  935. TestMaterialData testData;
  936. testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
  937. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  938. ErrorMessageFinder errorMessageFinder;
  939. errorMessageFinder.AddExpectedErrorMessage("not be changed at runtime because they impact Pipeline State Objects: general.MyBool");
  940. EXPECT_TRUE(testData.GetMaterial()->Compile());
  941. errorMessageFinder.CheckExpectedErrorsFound();
  942. }
  943. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_MultisampleCustomPositionCountIndex_Error)
  944. {
  945. using namespace AZ::RPI;
  946. const char* functorScript =
  947. R"(
  948. function GetMaterialPropertyDependencies()
  949. return {"general.MyBool"}
  950. end
  951. function GetShaderOptionDependencies()
  952. return {}
  953. end
  954. function Process(context)
  955. local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
  956. if(boolValue) then
  957. context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPositionCount(20)
  958. else
  959. context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPositionCount()
  960. end
  961. end
  962. )";
  963. TestMaterialData testData;
  964. testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
  965. testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed);
  966. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  967. ErrorMessageFinder errorMessageFinder;
  968. errorMessageFinder.AddExpectedErrorMessage("SetMultisampleCustomPositionCount(20) value is out of range. Must be less than 16.");
  969. EXPECT_TRUE(testData.GetMaterial()->Compile());
  970. errorMessageFinder.CheckExpectedErrorsFound();
  971. }
  972. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_MultisampleCustomPositionIndex_Error)
  973. {
  974. using namespace AZ::RPI;
  975. const char* functorScript =
  976. R"(
  977. function GetMaterialPropertyDependencies()
  978. return {"general.MyBool"}
  979. end
  980. function GetShaderOptionDependencies()
  981. return {}
  982. end
  983. function Process(context)
  984. local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
  985. if(boolValue) then
  986. context:GetShader(0):GetRenderStatesOverride():SetMultisampleCustomPosition(17, 0, 0)
  987. else
  988. context:GetShader(0):GetRenderStatesOverride():ClearMultisampleCustomPosition(18)
  989. end
  990. end
  991. )";
  992. TestMaterialData testData;
  993. ErrorMessageFinder errorMessageFinder;
  994. errorMessageFinder.AddExpectedErrorMessage("ClearMultisampleCustomPosition(18,...) index is out of range. Must be less than 16.");
  995. testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
  996. errorMessageFinder.CheckExpectedErrorsFound();
  997. testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed);
  998. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  999. errorMessageFinder.AddExpectedErrorMessage("SetMultisampleCustomPosition(17,...) index is out of range. Must be less than 16.");
  1000. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1001. errorMessageFinder.CheckExpectedErrorsFound();
  1002. }
  1003. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_BlendStateIndex_Error)
  1004. {
  1005. using namespace AZ::RPI;
  1006. const char* functorScript =
  1007. R"(
  1008. function GetMaterialPropertyDependencies()
  1009. return {"general.MyBool"}
  1010. end
  1011. function GetShaderOptionDependencies()
  1012. return {}
  1013. end
  1014. function Process(context)
  1015. local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool")
  1016. if(boolValue) then
  1017. context:GetShader(0):GetRenderStatesOverride():SetBlendEnabled(9, false)
  1018. else
  1019. context:GetShader(0):GetRenderStatesOverride():ClearBlendEnabled(10)
  1020. end
  1021. end
  1022. )";
  1023. TestMaterialData testData;
  1024. ErrorMessageFinder errorMessageFinder;
  1025. errorMessageFinder.AddExpectedErrorMessage("ClearBlendEnabled(10,...) index is out of range. Must be less than 8.");
  1026. testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript);
  1027. errorMessageFinder.CheckExpectedErrorsFound();
  1028. testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed);
  1029. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  1030. errorMessageFinder.AddExpectedErrorMessage("SetBlendEnabled(9,...) index is out of range. Must be less than 8.");
  1031. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1032. errorMessageFinder.CheckExpectedErrorsFound();
  1033. }
  1034. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_PipelineRuntimeContext_GetMaterialProperty_SetShaderEnabled_Bool)
  1035. {
  1036. using namespace AZ::RPI;
  1037. const char* functorScript =
  1038. R"(
  1039. function GetMaterialPropertyDependencies()
  1040. return {"EnableTestShader"}
  1041. end
  1042. function Process(context)
  1043. local value = context:GetMaterialPropertyValue_bool("EnableTestShader")
  1044. context:GetShaderByTag("TestShader"):SetEnabled(value)
  1045. end
  1046. )";
  1047. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), nullptr);
  1048. TestMaterialData testData;
  1049. testData.SetupMaterialPipeline(MaterialPropertyDataType::Bool, "general.TestBool", "EnableTestShader", functorScript);
  1050. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  1051. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1052. EXPECT_TRUE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1053. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  1054. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1055. EXPECT_FALSE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1056. }
  1057. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_PipelineRuntimeContext_SetShaderOption_Bool)
  1058. {
  1059. using namespace AZ::RPI;
  1060. const char* functorScript =
  1061. R"(
  1062. function GetMaterialPropertyDependencies()
  1063. return {"TestPipelineProperty"}
  1064. end
  1065. function GetShaderOptionDependencies()
  1066. return {"o_bool"}
  1067. end
  1068. function Process(context)
  1069. local value = context:GetMaterialPropertyValue_bool("TestPipelineProperty")
  1070. context:SetShaderOptionValue_bool("o_bool", value)
  1071. end
  1072. )";
  1073. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  1074. TestMaterialData testData;
  1075. testData.SetupMaterialPipeline(options, MaterialPropertyDataType::Bool, "general.TestBool", "TestPipelineProperty", "o_bool", functorScript);
  1076. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  1077. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1078. EXPECT_EQ(1, testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[0].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
  1079. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  1080. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1081. EXPECT_EQ(0, testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[0].GetShaderOptions()->GetValue(Name{"o_bool"}).GetIndex());
  1082. }
  1083. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_PipelineRuntimeContext_SetShaderOption_UInt)
  1084. {
  1085. using namespace AZ::RPI;
  1086. const char* functorScript =
  1087. R"(
  1088. function GetMaterialPropertyDependencies()
  1089. return {"TestPipelineProperty"}
  1090. end
  1091. function GetShaderOptionDependencies()
  1092. return {"o_uint"}
  1093. end
  1094. function Process(context)
  1095. local value = context:GetMaterialPropertyValue_int("TestPipelineProperty")
  1096. context:SetShaderOptionValue_uint("o_uint", value * 2)
  1097. end
  1098. )";
  1099. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  1100. TestMaterialData testData;
  1101. testData.SetupMaterialPipeline(options, MaterialPropertyDataType::Int, "general.TestInt", "TestPipelineProperty", "o_uint", functorScript);
  1102. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{6});
  1103. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1104. EXPECT_EQ(12, testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[0].GetShaderOptions()->GetValue(Name{"o_uint"}).GetIndex());
  1105. }
  1106. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_PipelineRuntimeContext_SetShaderOption_Enum)
  1107. {
  1108. using namespace AZ::RPI;
  1109. const char* functorScript =
  1110. R"(
  1111. function GetMaterialPropertyDependencies()
  1112. return {"TestPipelineProperty"}
  1113. end
  1114. function GetShaderOptionDependencies()
  1115. return {"o_enum"}
  1116. end
  1117. function Process(context)
  1118. local useHighQuality = context:GetMaterialPropertyValue_bool("TestPipelineProperty")
  1119. if (useHighQuality) then
  1120. context:SetShaderOptionValue_enum("o_enum", "Quality::High")
  1121. else
  1122. context:SetShaderOptionValue_enum("o_enum", "Quality::Medium")
  1123. end
  1124. end
  1125. )";
  1126. AZ::RPI::Ptr<AZ::RPI::ShaderOptionGroupLayout> options = CreateCommonTestShaderOptionsLayout();
  1127. TestMaterialData testData;
  1128. testData.SetupMaterialPipeline(options, MaterialPropertyDataType::Bool, "general.UseHighQuality", "TestPipelineProperty", "o_enum", functorScript);
  1129. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  1130. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1131. EXPECT_EQ(2, testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[0].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
  1132. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  1133. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1134. EXPECT_EQ(1, testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[0].GetShaderOptions()->GetValue(Name{"o_enum"}).GetIndex());
  1135. }
  1136. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_SetInternalProperty_Bool)
  1137. {
  1138. using namespace AZ::RPI;
  1139. // One functor passes a property value to an internal property of the material pipeline,
  1140. // then a material pipeline functor uses that value to enable or disable a shader.
  1141. const char* functorScript =
  1142. R"(
  1143. function GetMaterialPropertyDependencies()
  1144. return {"general.TestProperty"}
  1145. end
  1146. function Process(context)
  1147. local value = context:GetMaterialPropertyValue_bool("general.TestProperty")
  1148. context:SetInternalMaterialPropertyValue_bool("TestPipelineProperty", value)
  1149. end
  1150. )";
  1151. const char* functorScriptForPipeline =
  1152. R"(
  1153. function GetMaterialPropertyDependencies()
  1154. return {"TestPipelineProperty"}
  1155. end
  1156. function Process(context)
  1157. local value = context:GetMaterialPropertyValue_bool("TestPipelineProperty")
  1158. context:GetShaderByTag("TestShader"):SetEnabled(value)
  1159. end
  1160. )";
  1161. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), nullptr);
  1162. TestMaterialData testData;
  1163. testData.SetupMaterialPipeline(
  1164. MaterialPropertyDataType::Bool, "general.TestProperty", functorScript,
  1165. MaterialPropertyDataType::Bool, "TestPipelineProperty", functorScriptForPipeline);
  1166. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true});
  1167. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1168. EXPECT_TRUE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1169. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{false});
  1170. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1171. EXPECT_FALSE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1172. }
  1173. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetInternalProperty_Float)
  1174. {
  1175. using namespace AZ::RPI;
  1176. // One functor passes a property value to an internal property of the material pipeline,
  1177. // then a material pipeline functor uses that value to enable or disable a shader.
  1178. const char* functorScript =
  1179. R"(
  1180. function GetMaterialPropertyDependencies()
  1181. return {"general.TestProperty"}
  1182. end
  1183. function Process(context)
  1184. local value = context:GetMaterialPropertyValue_float("general.TestProperty")
  1185. context:SetInternalMaterialPropertyValue_float("TestPipelineProperty", value)
  1186. end
  1187. )";
  1188. const char* functorScriptForPipeline =
  1189. R"(
  1190. function GetMaterialPropertyDependencies()
  1191. return {"TestPipelineProperty"}
  1192. end
  1193. function Process(context)
  1194. local value = context:GetMaterialPropertyValue_float("TestPipelineProperty")
  1195. context:GetShaderByTag("TestShader"):SetEnabled(value > 0.0)
  1196. end
  1197. )";
  1198. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), nullptr);
  1199. TestMaterialData testData;
  1200. testData.SetupMaterialPipeline(
  1201. MaterialPropertyDataType::Float, "general.TestProperty", functorScript,
  1202. MaterialPropertyDataType::Float, "TestPipelineProperty", functorScriptForPipeline);
  1203. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1.0f});
  1204. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1205. EXPECT_TRUE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1206. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{-1.0f});
  1207. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1208. EXPECT_FALSE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1209. }
  1210. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetInternalProperty_Int)
  1211. {
  1212. using namespace AZ::RPI;
  1213. // One functor passes a property value to an internal property of the material pipeline,
  1214. // then a material pipeline functor uses that value to enable or disable a shader.
  1215. const char* functorScript =
  1216. R"(
  1217. function GetMaterialPropertyDependencies()
  1218. return {"general.TestProperty"}
  1219. end
  1220. function Process(context)
  1221. local value = context:GetMaterialPropertyValue_int("general.TestProperty")
  1222. context:SetInternalMaterialPropertyValue_int("TestPipelineProperty", value)
  1223. end
  1224. )";
  1225. const char* functorScriptForPipeline =
  1226. R"(
  1227. function GetMaterialPropertyDependencies()
  1228. return {"TestPipelineProperty"}
  1229. end
  1230. function Process(context)
  1231. local value = context:GetMaterialPropertyValue_int("TestPipelineProperty")
  1232. context:GetShaderByTag("TestShader"):SetEnabled(value ~= 0)
  1233. end
  1234. )";
  1235. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), nullptr);
  1236. TestMaterialData testData;
  1237. testData.SetupMaterialPipeline(
  1238. MaterialPropertyDataType::Int, "general.TestProperty", functorScript,
  1239. MaterialPropertyDataType::Int, "TestPipelineProperty", functorScriptForPipeline);
  1240. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{-1});
  1241. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1242. EXPECT_TRUE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1243. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0});
  1244. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1245. EXPECT_FALSE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1246. }
  1247. TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_GetMaterialProperty_SetInternalProperty_UInt)
  1248. {
  1249. using namespace AZ::RPI;
  1250. // One functor passes a property value to an internal property of the material pipeline,
  1251. // then a material pipeline functor uses that value to enable or disable a shader.
  1252. const char* functorScript =
  1253. R"(
  1254. function GetMaterialPropertyDependencies()
  1255. return {"general.TestProperty"}
  1256. end
  1257. function Process(context)
  1258. local value = context:GetMaterialPropertyValue_uint("general.TestProperty")
  1259. context:SetInternalMaterialPropertyValue_uint("TestPipelineProperty", value)
  1260. end
  1261. )";
  1262. const char* functorScriptForPipeline =
  1263. R"(
  1264. function GetMaterialPropertyDependencies()
  1265. return {"TestPipelineProperty"}
  1266. end
  1267. function Process(context)
  1268. local value = context:GetMaterialPropertyValue_uint("TestPipelineProperty")
  1269. context:GetShaderByTag("TestShader"):SetEnabled(value ~= 0)
  1270. end
  1271. )";
  1272. auto shaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), nullptr);
  1273. TestMaterialData testData;
  1274. testData.SetupMaterialPipeline(
  1275. MaterialPropertyDataType::UInt, "general.TestProperty", functorScript,
  1276. MaterialPropertyDataType::UInt, "TestPipelineProperty", functorScriptForPipeline);
  1277. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{1u});
  1278. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1279. EXPECT_TRUE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1280. testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{0u});
  1281. EXPECT_TRUE(testData.GetMaterial()->Compile());
  1282. EXPECT_FALSE(testData.GetMaterial()->GetShaderCollection(Name{"TestPipeline"})[Name{"TestShader"}].IsEnabled());
  1283. }
  1284. }