3
0

ShaderBuildArgumentsTests.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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 <AzCore/UnitTest/TestTypes.h>
  10. #include <AzCore/std/algorithm.h>
  11. #include <Atom/RPI.Edit/Common/JsonUtils.h>
  12. #include <Atom/RPI.Edit/Shader/ShaderSourceData.h>
  13. #include <Atom/RHI.Edit/Utils.h>
  14. #include "Common/ShaderBuilderTestFixture.h"
  15. #include <ShaderBuildArgumentsManager.h>
  16. namespace UnitTest
  17. {
  18. class ShaderBuildArgumentsTests : public ShaderBuilderTestFixture
  19. {
  20. protected:
  21. AZ::RHI::ShaderBuildArguments CreateInitializedShaderBuildArguments()
  22. {
  23. AZ::RHI::ShaderBuildArguments arguments(
  24. true,
  25. { "-cpp1", "-cpp2", "-DMACRO1=1", "-DMACRO2=2" },
  26. { "--azslc1", "--azslc2", "--azslc3" },
  27. { "--dxc1" },
  28. { "--spirv1", "--spirv2", "--spirv3", "--spirv4" },
  29. { "--metalair1", "--metalair2" },
  30. { "--metallib1", "--metallib2", "--metallib3" });
  31. return arguments;
  32. }
  33. AZ::ShaderBuilder::ShaderBuildArgumentsManager CreateInitializedManager(
  34. AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && removeBuildArgumentsMap,
  35. AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> && addBuildArgumentsMap)
  36. {
  37. AZ::ShaderBuilder::ShaderBuildArgumentsManager argsManager;
  38. argsManager.Init(AZStd::move(removeBuildArgumentsMap), AZStd::move(addBuildArgumentsMap));
  39. return argsManager;
  40. }
  41. // Because macros are evil, this short named function allows to write easy
  42. // EXPECT_EQ() expressions with string literal vector.
  43. // Example:
  44. // EXPECT_EQ(someVector, VSTR({"str1", "str2"}))
  45. static AZStd::vector<AZStd::string> VSTR(AZStd::vector<AZStd::string> args)
  46. {
  47. return args;
  48. }
  49. }; // class ShaderBuildArgumentsTests
  50. TEST_F(ShaderBuildArgumentsTests, CreateShaderBuildArguments_AllArraysMustBeEmpty)
  51. {
  52. AZ::RHI::ShaderBuildArguments arguments;
  53. EXPECT_FALSE(arguments.m_generateDebugInfo);
  54. EXPECT_TRUE(arguments.m_preprocessorArguments.empty());
  55. EXPECT_TRUE(arguments.m_azslcArguments.empty());
  56. EXPECT_TRUE(arguments.m_dxcArguments.empty());
  57. EXPECT_TRUE(arguments.m_spirvCrossArguments.empty());
  58. EXPECT_TRUE(arguments.m_metalAirArguments.empty());
  59. EXPECT_TRUE(arguments.m_metalLibArguments.empty());
  60. }
  61. TEST_F(ShaderBuildArgumentsTests, AddEmptyShaderBuildArguments_AllArraysMustBeEmpty)
  62. {
  63. AZ::RHI::ShaderBuildArguments lhs;
  64. AZ::RHI::ShaderBuildArguments rhs;
  65. AZ::RHI::ShaderBuildArguments arguments = lhs + rhs;
  66. EXPECT_FALSE(arguments.m_generateDebugInfo);
  67. EXPECT_TRUE(arguments.m_preprocessorArguments.empty());
  68. EXPECT_TRUE(arguments.m_azslcArguments.empty());
  69. EXPECT_TRUE(arguments.m_dxcArguments.empty());
  70. EXPECT_TRUE(arguments.m_spirvCrossArguments.empty());
  71. EXPECT_TRUE(arguments.m_metalAirArguments.empty());
  72. EXPECT_TRUE(arguments.m_metalLibArguments.empty());
  73. }
  74. TEST_F(ShaderBuildArgumentsTests, SubtractEmptyShaderBuildArguments_AllArraysMustBeEmpty)
  75. {
  76. AZ::RHI::ShaderBuildArguments lhs;
  77. AZ::RHI::ShaderBuildArguments rhs;
  78. AZ::RHI::ShaderBuildArguments arguments = lhs - rhs;
  79. EXPECT_FALSE(arguments.m_generateDebugInfo);
  80. EXPECT_TRUE(arguments.m_preprocessorArguments.empty());
  81. EXPECT_TRUE(arguments.m_azslcArguments.empty());
  82. EXPECT_TRUE(arguments.m_dxcArguments.empty());
  83. EXPECT_TRUE(arguments.m_spirvCrossArguments.empty());
  84. EXPECT_TRUE(arguments.m_metalAirArguments.empty());
  85. EXPECT_TRUE(arguments.m_metalLibArguments.empty());
  86. }
  87. TEST_F(ShaderBuildArgumentsTests, AccumulateEmptyShaderBuildArguments_AllArraysMustBeEmpty)
  88. {
  89. AZ::RHI::ShaderBuildArguments arguments;
  90. AZ::RHI::ShaderBuildArguments rhs;
  91. arguments += rhs;
  92. EXPECT_FALSE(arguments.m_generateDebugInfo);
  93. EXPECT_TRUE(arguments.m_preprocessorArguments.empty());
  94. EXPECT_TRUE(arguments.m_azslcArguments.empty());
  95. EXPECT_TRUE(arguments.m_dxcArguments.empty());
  96. EXPECT_TRUE(arguments.m_spirvCrossArguments.empty());
  97. EXPECT_TRUE(arguments.m_metalAirArguments.empty());
  98. EXPECT_TRUE(arguments.m_metalLibArguments.empty());
  99. }
  100. TEST_F(ShaderBuildArgumentsTests, SubtractEqualEmptyShaderBuildArguments_AllArraysMustBeEmpty)
  101. {
  102. AZ::RHI::ShaderBuildArguments arguments;
  103. AZ::RHI::ShaderBuildArguments rhs;
  104. arguments -= rhs;
  105. EXPECT_FALSE(arguments.m_generateDebugInfo);
  106. EXPECT_TRUE(arguments.m_preprocessorArguments.empty());
  107. EXPECT_TRUE(arguments.m_azslcArguments.empty());
  108. EXPECT_TRUE(arguments.m_dxcArguments.empty());
  109. EXPECT_TRUE(arguments.m_spirvCrossArguments.empty());
  110. EXPECT_TRUE(arguments.m_metalAirArguments.empty());
  111. EXPECT_TRUE(arguments.m_metalLibArguments.empty());
  112. }
  113. TEST_F(ShaderBuildArgumentsTests, InitializeShaderBuildArguments_AddEmpty_RemainsUnchanged)
  114. {
  115. AZ::RHI::ShaderBuildArguments arguments = CreateInitializedShaderBuildArguments();
  116. const auto generateDebugInfo = arguments.m_generateDebugInfo;
  117. const auto preprocessorArgumentsSize = arguments.m_preprocessorArguments.size();
  118. const auto azslcArgumentsSize = arguments.m_azslcArguments.size();
  119. const auto dxcArgumentsSize = arguments.m_dxcArguments.size();
  120. const auto spirvCrossArgumentsSize = arguments.m_spirvCrossArguments.size();
  121. const auto metalAirArgumentsSize = arguments.m_metalAirArguments.size();
  122. const auto metalLibArgumentsSize = arguments.m_metalLibArguments.size();
  123. AZ::RHI::ShaderBuildArguments rhs;
  124. arguments += rhs;
  125. EXPECT_EQ(generateDebugInfo, arguments.m_generateDebugInfo);
  126. EXPECT_EQ(preprocessorArgumentsSize, arguments.m_preprocessorArguments.size());
  127. EXPECT_EQ(azslcArgumentsSize, arguments.m_azslcArguments.size());
  128. EXPECT_EQ(dxcArgumentsSize, arguments.m_dxcArguments.size());
  129. EXPECT_EQ(spirvCrossArgumentsSize, arguments.m_spirvCrossArguments.size());
  130. EXPECT_EQ(metalAirArgumentsSize, arguments.m_metalAirArguments.size());
  131. EXPECT_EQ(metalLibArgumentsSize, arguments.m_metalLibArguments.size());
  132. }
  133. TEST_F(ShaderBuildArgumentsTests, InitializeShaderBuildArguments_SubtractEmpty_RemainsUnchanged)
  134. {
  135. AZ::RHI::ShaderBuildArguments arguments = CreateInitializedShaderBuildArguments();
  136. const auto generateDebugInfo = arguments.m_generateDebugInfo;
  137. const auto preprocessorArgumentsSize = arguments.m_preprocessorArguments.size();
  138. const auto azslcArgumentsSize = arguments.m_azslcArguments.size();
  139. const auto dxcArgumentsSize = arguments.m_dxcArguments.size();
  140. const auto spirvCrossArgumentsSize = arguments.m_spirvCrossArguments.size();
  141. const auto metalAirArgumentsSize = arguments.m_metalAirArguments.size();
  142. const auto metalLibArgumentsSize = arguments.m_metalLibArguments.size();
  143. AZ::RHI::ShaderBuildArguments rhs;
  144. arguments -= rhs;
  145. EXPECT_EQ(generateDebugInfo, arguments.m_generateDebugInfo);
  146. EXPECT_EQ(preprocessorArgumentsSize, arguments.m_preprocessorArguments.size());
  147. EXPECT_EQ(azslcArgumentsSize, arguments.m_azslcArguments.size());
  148. EXPECT_EQ(dxcArgumentsSize, arguments.m_dxcArguments.size());
  149. EXPECT_EQ(spirvCrossArgumentsSize, arguments.m_spirvCrossArguments.size());
  150. EXPECT_EQ(metalAirArgumentsSize, arguments.m_metalAirArguments.size());
  151. EXPECT_EQ(metalLibArgumentsSize, arguments.m_metalLibArguments.size());
  152. }
  153. TEST_F(ShaderBuildArgumentsTests, InitializeShaderBuildArguments_AddSameArguments_RemainsUnchanged)
  154. {
  155. AZ::RHI::ShaderBuildArguments arguments = CreateInitializedShaderBuildArguments();
  156. AZ::RHI::ShaderBuildArguments sameArguments = CreateInitializedShaderBuildArguments();
  157. arguments += sameArguments;
  158. EXPECT_EQ(arguments.m_generateDebugInfo, sameArguments.m_generateDebugInfo);
  159. EXPECT_EQ(arguments.m_preprocessorArguments, sameArguments.m_preprocessorArguments);
  160. EXPECT_EQ(arguments.m_azslcArguments, sameArguments.m_azslcArguments);
  161. EXPECT_EQ(arguments.m_dxcArguments, sameArguments.m_dxcArguments);
  162. EXPECT_EQ(arguments.m_spirvCrossArguments, sameArguments.m_spirvCrossArguments);
  163. EXPECT_EQ(arguments.m_metalAirArguments, sameArguments.m_metalAirArguments);
  164. EXPECT_EQ(arguments.m_metalLibArguments, sameArguments.m_metalLibArguments);
  165. }
  166. TEST_F(ShaderBuildArgumentsTests, InitializeShaderBuildArguments_SubtractSameArguments_ChangesToEmpty)
  167. {
  168. AZ::RHI::ShaderBuildArguments arguments = CreateInitializedShaderBuildArguments();
  169. AZ::RHI::ShaderBuildArguments sameArguments = CreateInitializedShaderBuildArguments();
  170. arguments -= sameArguments;
  171. EXPECT_FALSE(arguments.m_generateDebugInfo);
  172. EXPECT_TRUE(arguments.m_preprocessorArguments.empty());
  173. EXPECT_TRUE(arguments.m_azslcArguments.empty());
  174. EXPECT_TRUE(arguments.m_dxcArguments.empty());
  175. EXPECT_TRUE(arguments.m_spirvCrossArguments.empty());
  176. EXPECT_TRUE(arguments.m_metalAirArguments.empty());
  177. EXPECT_TRUE(arguments.m_metalLibArguments.empty());
  178. }
  179. TEST_F(ShaderBuildArgumentsTests, CreateEmtpyShaderBuildArguments_AppendDefinitionsSomeWithSpaces_AppendSuccessful)
  180. {
  181. AZ::RHI::ShaderBuildArguments arguments;
  182. auto definitions = VSTR({"MACRO1", "MACRO2=VALUE2", " MACRO3", "MACRO4 ", " MACRO5=VALUE5 "});
  183. arguments.AppendDefinitions(definitions);
  184. EXPECT_EQ(arguments.m_preprocessorArguments, VSTR({ "-DMACRO1", "-DMACRO2=VALUE2", "-DMACRO3", "-DMACRO4", "-DMACRO5=VALUE5" }));
  185. }
  186. TEST_F(ShaderBuildArgumentsTests, InitializeShaderBuildArguments_AppendDefinitionsWithTypos_ExpectError)
  187. {
  188. AZ::RHI::ShaderBuildArguments arguments = CreateInitializedShaderBuildArguments();
  189. auto definitions = VSTR({"-DMACRO1", "MACRO2=VALUE2"}); // Not allowed to start with '-'
  190. AZ_TEST_START_TRACE_SUPPRESSION;
  191. EXPECT_FALSE(arguments.AppendDefinitions(definitions) >= 0);
  192. AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
  193. definitions = VSTR({"MACRO2 = VALUE2", "MACRO1"}); // Not allowed to have spaces in between.
  194. AZ_TEST_START_TRACE_SUPPRESSION;
  195. EXPECT_FALSE(arguments.AppendDefinitions(definitions) >= 0);
  196. AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
  197. }
  198. TEST_F(ShaderBuildArgumentsTests, InitializeShaderBuildArgumentsManager_ValidateAllOperations)
  199. {
  200. // Let's initialize the arguments.
  201. AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> removeBuildArgumentsMap;
  202. AZStd::unordered_map<AZStd::string, AZ::RHI::ShaderBuildArguments> addBuildArgumentsMap;
  203. // Globals. The name of the global arguments is always the empty string.
  204. // This will be level 1.
  205. addBuildArgumentsMap.emplace("", AZ::RHI::ShaderBuildArguments(false
  206. , { "--cpp1" }
  207. , { "--azslc1" }
  208. , { "--dxc1" }
  209. , { "--spirv1" }
  210. , { "--metalair1" }
  211. , { "--metallib1" })
  212. );
  213. removeBuildArgumentsMap.emplace("", AZ::RHI::ShaderBuildArguments());
  214. // Simulates common arguments for all RHIs under the "Windows" platform.
  215. addBuildArgumentsMap.emplace("Windows", AZ::RHI::ShaderBuildArguments(false
  216. , { "--cpp2w" }
  217. , { "--azslc2w" }
  218. , { "--dxc2w" }
  219. , { "--spirv2w" }
  220. , { "--metalair2w" }
  221. , { "--metallib2w" })
  222. );
  223. removeBuildArgumentsMap.emplace("Windows", AZ::RHI::ShaderBuildArguments());
  224. // Simulates "dx12" arguments for "Windows"
  225. addBuildArgumentsMap.emplace("Windows.dx12", AZ::RHI::ShaderBuildArguments(false
  226. , { "--cpp3w" }
  227. , { "--azslc3w" }
  228. , { "--dxc3w" }
  229. , { "--spirv3w" }
  230. , { "--metalair3w" }
  231. , { "--metallib3w" })
  232. );
  233. removeBuildArgumentsMap.emplace("Windows.dx12", AZ::RHI::ShaderBuildArguments());
  234. // Simulates "vulkan" arguments for "Windows"
  235. addBuildArgumentsMap.emplace("Windows.vulkan", AZ::RHI::ShaderBuildArguments(true
  236. , { "--cpp4w" }
  237. , { "--azslc4w" }
  238. , { "--dxc4w" }
  239. , { "--spirv4w" }
  240. , { "--metalair4w" }
  241. , { "--metallib4w" })
  242. );
  243. removeBuildArgumentsMap.emplace("Windows.vulkan", AZ::RHI::ShaderBuildArguments());
  244. // Simulates "vulkan" arguments for "Linux"
  245. addBuildArgumentsMap.emplace("Linux.vulkan", AZ::RHI::ShaderBuildArguments(true
  246. , { "--cpp3l" }
  247. , { "--azslc3l" }
  248. , { "--dxc3l" }
  249. , { "--spirv3l" }
  250. , { "--metalair3l" }
  251. , { "--metallib3l" })
  252. );
  253. removeBuildArgumentsMap.emplace("Linux.vulkan", AZ::RHI::ShaderBuildArguments());
  254. // Simulates some arguments customized by a .shader.
  255. AZ::RHI::ShaderBuildArguments addShaderArgs(true
  256. , { "--cpp5s" }
  257. , { "--azslc5s" }
  258. , { "--dxc5s" }
  259. , { "--spirv5s" }
  260. , { "--metalair5s" }
  261. , { "--metallib5s" });
  262. AZ::RHI::ShaderBuildArguments removeShaderArgs;
  263. // Simulates some arguments customized by a supervariant inside the .shader.
  264. AZ::RHI::ShaderBuildArguments addSuperVariantArgs(true
  265. , { "--cpp6sv" }
  266. , { "--azslc6sv" }
  267. , { "--dxc6sv" }
  268. , { "--spirv6sv" }
  269. , { "--metalair6sv" }
  270. , { "--metallib6sv" });
  271. AZ::RHI::ShaderBuildArguments removeSuperVariantArgs(false
  272. , { }
  273. , { }
  274. , { }
  275. , { "--spirv5s" }
  276. , { "--metalair5s" }
  277. , { "--metallib5s" });
  278. AZ::ShaderBuilder::ShaderBuildArgumentsManager argsManager = CreateInitializedManager(AZStd::move(removeBuildArgumentsMap), AZStd::move(addBuildArgumentsMap));
  279. // We have a fully initialized ShaderBuildArgumentsManager. The "" (global) set of arguments is the starting set (or scope) of
  280. // arguments
  281. auto buildArgs = argsManager.GetCurrentArguments();
  282. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  283. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  284. // Simulate for loop across all platforms and across RHIs per platform.
  285. {
  286. buildArgs = argsManager.PushArgumentScope("Windows");
  287. // Now the current set of arguments at the top of the stack are the addition of the global arguments, and "Windows" arguments.
  288. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w" }));
  289. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w" }));
  290. // Simulate looping across RHIs for Windows.
  291. {
  292. buildArgs = argsManager.PushArgumentScope("dx12");
  293. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp3w" }));
  294. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc3w" }));
  295. {
  296. // Simulate shader arguments.
  297. buildArgs = argsManager.PushArgumentScope(removeShaderArgs, addShaderArgs, {"MACRO1 ", " MACRO2=VALUE2"}); // Spaces in MACROxx added on purpose.
  298. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp3w", "-DMACRO1", "-DMACRO2=VALUE2", "--cpp5s"}));
  299. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc3w", "--dxc5s" }));
  300. EXPECT_EQ(buildArgs.m_spirvCrossArguments, VSTR({ "--spirv1", "--spirv2w", "--spirv3w", "--spirv5s" }));
  301. EXPECT_EQ(buildArgs.m_metalAirArguments, VSTR({ "--metalair1", "--metalair2w", "--metalair3w", "--metalair5s" }));
  302. EXPECT_EQ(buildArgs.m_metalLibArguments, VSTR({ "--metallib1", "--metallib2w", "--metallib3w", "--metallib5s" }));
  303. // Simulate supervariant arguments.
  304. buildArgs = argsManager.PushArgumentScope(removeSuperVariantArgs, addSuperVariantArgs, VSTR({" MACRO3 ", " MACRO4=VALUE4 "})); // Spaces in MACROxx added on purpose.
  305. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp3w", "-DMACRO1", "-DMACRO2=VALUE2", "--cpp5s", "-DMACRO3", "-DMACRO4=VALUE4", "--cpp6sv"}));
  306. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc3w", "--dxc5s", "--dxc6sv" }));
  307. // Notice that in this case the supervariant removes the shader arguments "--spirv5s", "--metalair5s" & "--metallib5s"
  308. EXPECT_EQ(buildArgs.m_spirvCrossArguments, VSTR({ "--spirv1", "--spirv2w", "--spirv3w", "--spirv6sv" }));
  309. EXPECT_EQ(buildArgs.m_metalAirArguments, VSTR({ "--metalair1", "--metalair2w", "--metalair3w", "--metalair6sv" }));
  310. EXPECT_EQ(buildArgs.m_metalLibArguments, VSTR({ "--metallib1", "--metallib2w", "--metallib3w", "--metallib6sv" }));
  311. // Pop the supervariant arguments.
  312. argsManager.PopArgumentScope();
  313. buildArgs = argsManager.GetCurrentArguments();
  314. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp3w", "-DMACRO1", "-DMACRO2=VALUE2", "--cpp5s"}));
  315. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc3w", "--dxc5s" }));
  316. EXPECT_EQ(buildArgs.m_spirvCrossArguments, VSTR({ "--spirv1", "--spirv2w", "--spirv3w", "--spirv5s" }));
  317. EXPECT_EQ(buildArgs.m_metalAirArguments, VSTR({ "--metalair1", "--metalair2w", "--metalair3w", "--metalair5s" }));
  318. EXPECT_EQ(buildArgs.m_metalLibArguments, VSTR({ "--metallib1", "--metallib2w", "--metallib3w", "--metallib5s" }));
  319. // Pop the shader arguments.
  320. argsManager.PopArgumentScope();
  321. buildArgs = argsManager.GetCurrentArguments();
  322. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp3w" }));
  323. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc3w" }));
  324. }
  325. // Pop the rhi before pushing the next rhi.
  326. argsManager.PopArgumentScope();
  327. buildArgs = argsManager.GetCurrentArguments();
  328. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w" }));
  329. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w" }));
  330. // Push the "vulkan" arguments.
  331. buildArgs = argsManager.PushArgumentScope("vulkan");
  332. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp4w" }));
  333. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc4w" }));
  334. {
  335. // Simulate shader arguments.
  336. buildArgs = argsManager.PushArgumentScope(removeShaderArgs, addShaderArgs, {});
  337. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp4w", "--cpp5s" }));
  338. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc4w", "--dxc5s" }));
  339. EXPECT_EQ(buildArgs.m_spirvCrossArguments, VSTR({ "--spirv1", "--spirv2w", "--spirv4w", "--spirv5s" }));
  340. EXPECT_EQ(buildArgs.m_metalAirArguments, VSTR({ "--metalair1", "--metalair2w", "--metalair4w", "--metalair5s" }));
  341. EXPECT_EQ(buildArgs.m_metalLibArguments, VSTR({ "--metallib1", "--metallib2w", "--metallib4w", "--metallib5s" }));
  342. // Simulate supervariant arguments.
  343. buildArgs = argsManager.PushArgumentScope(removeSuperVariantArgs, addSuperVariantArgs, {});
  344. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp4w", "--cpp5s", "--cpp6sv" }));
  345. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc4w", "--dxc5s", "--dxc6sv" }));
  346. // Notice that in this case the supervariant removes the shader arguments "--spirv5s", "--metalair5s" & "--metallib5s"
  347. EXPECT_EQ(buildArgs.m_spirvCrossArguments, VSTR({ "--spirv1", "--spirv2w", "--spirv4w", "--spirv6sv" }));
  348. EXPECT_EQ(buildArgs.m_metalAirArguments, VSTR({ "--metalair1", "--metalair2w", "--metalair4w", "--metalair6sv" }));
  349. EXPECT_EQ(buildArgs.m_metalLibArguments, VSTR({ "--metallib1", "--metallib2w", "--metallib4w", "--metallib6sv" }));
  350. // Pop the supervariant arguments.
  351. argsManager.PopArgumentScope();
  352. buildArgs = argsManager.GetCurrentArguments();
  353. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp4w", "--cpp5s" }));
  354. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc4w", "--dxc5s" }));
  355. EXPECT_EQ(buildArgs.m_spirvCrossArguments, VSTR({ "--spirv1", "--spirv2w", "--spirv4w", "--spirv5s" }));
  356. EXPECT_EQ(buildArgs.m_metalAirArguments, VSTR({ "--metalair1", "--metalair2w", "--metalair4w", "--metalair5s" }));
  357. EXPECT_EQ(buildArgs.m_metalLibArguments, VSTR({ "--metallib1", "--metallib2w", "--metallib4w", "--metallib5s" }));
  358. // Pop the shader arguments.
  359. argsManager.PopArgumentScope();
  360. buildArgs = argsManager.GetCurrentArguments();
  361. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w", "--cpp4w" }));
  362. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w", "--dxc4w" }));
  363. }
  364. // Pop the rhi before pushing the next rhi.
  365. argsManager.PopArgumentScope();
  366. buildArgs = argsManager.GetCurrentArguments();
  367. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp2w" }));
  368. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc2w" }));
  369. }
  370. // Pop the platform before changing Platforms.
  371. argsManager.PopArgumentScope();
  372. buildArgs = argsManager.GetCurrentArguments();
  373. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  374. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  375. buildArgs = argsManager.PushArgumentScope("Linux");
  376. // In this test case, the platform "Linux" does not customize the arguments.
  377. // We expect the same arguments as before.
  378. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  379. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  380. // Simulate looping across RHIs for Linux.
  381. {
  382. buildArgs = argsManager.PushArgumentScope("dx12");
  383. // Linux doesn't work with dx12. Expect arguments to be unchanged.
  384. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  385. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  386. // Pop the rhi before pushing the next rhi.
  387. argsManager.PopArgumentScope();
  388. buildArgs = argsManager.GetCurrentArguments();
  389. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  390. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  391. // Push the "vulkan" arguments.
  392. buildArgs = argsManager.PushArgumentScope("vulkan");
  393. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1", "--cpp3l" }));
  394. EXPECT_EQ(buildArgs.m_dxcArguments, VSTR({ "--dxc1", "--dxc3l" }));
  395. // Pop the rhi before pushing the next rhi.
  396. argsManager.PopArgumentScope();
  397. buildArgs = argsManager.GetCurrentArguments();
  398. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  399. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  400. }
  401. // Pop the platform before changing Platforms.
  402. argsManager.PopArgumentScope();
  403. buildArgs = argsManager.GetCurrentArguments();
  404. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  405. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  406. }
  407. // At the moment the current scope is the global scope, named "".
  408. buildArgs = argsManager.GetCurrentArguments();
  409. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  410. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  411. // No matter how many times We pop, the global set of arguments is never removed.
  412. argsManager.PopArgumentScope();
  413. argsManager.PopArgumentScope();
  414. argsManager.PopArgumentScope();
  415. buildArgs = argsManager.GetCurrentArguments();
  416. EXPECT_EQ(buildArgs.m_preprocessorArguments, VSTR({ "--cpp1" }));
  417. EXPECT_EQ(buildArgs.m_azslcArguments, VSTR({ "--azslc1" }));
  418. }
  419. } //namespace UnitTest
  420. AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);