DrawPacketTests.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  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 "RHITestFixture.h"
  9. #include <Atom/RHI/DeviceDrawPacket.h>
  10. #include <Atom/RHI/DeviceDrawPacketBuilder.h>
  11. #include <Atom/RHI/DrawListContext.h>
  12. #include <Atom/RHI/DrawListTagRegistry.h>
  13. #include <Atom/RHI/DevicePipelineState.h>
  14. #include <AzCore/Math/Random.h>
  15. #include <AzCore/std/sort.h>
  16. #include <Tests/Factory.h>
  17. namespace UnitTest
  18. {
  19. using namespace AZ;
  20. struct DrawItemData
  21. {
  22. DrawItemData(SimpleLcgRandom& random, const RHI::DeviceBuffer* bufferEmpty, const RHI::DevicePipelineState* psoEmpty)
  23. {
  24. m_pipelineState = psoEmpty;
  25. // Fill with deterministic random data to compare against.
  26. for (auto& streamBufferView : m_streamBufferViews)
  27. {
  28. streamBufferView = RHI::DeviceStreamBufferView{ *bufferEmpty, random.GetRandom(), random.GetRandom(), random.GetRandom() };
  29. }
  30. m_tag = RHI::DrawListTag(random.GetRandom() % RHI::Limits::Pipeline::DrawListTagCountMax);
  31. m_stencilRef = static_cast<uint8_t>(random.GetRandom());
  32. m_sortKey = random.GetRandom();
  33. }
  34. AZStd::array<RHI::DeviceStreamBufferView, RHI::Limits::Pipeline::StreamCountMax> m_streamBufferViews;
  35. const RHI::DevicePipelineState* m_pipelineState;
  36. RHI::DrawListTag m_tag;
  37. RHI::DrawItemSortKey m_sortKey;
  38. uint8_t m_stencilRef;
  39. };
  40. struct DrawPacketData
  41. {
  42. const size_t DrawItemCountMax = 8;
  43. DrawPacketData(SimpleLcgRandom& random)
  44. {
  45. m_bufferEmpty = RHI::Factory::Get().CreateBuffer();
  46. m_psoEmpty = RHI::Factory::Get().CreatePipelineState();
  47. for (auto& srg : m_srgs)
  48. {
  49. srg = RHI::Factory::Get().CreateShaderResourceGroup();
  50. }
  51. unsigned int* data = reinterpret_cast<unsigned int*>(m_rootConstants.data());
  52. for (uint32_t i = 0; i < m_rootConstants.size()/sizeof(unsigned int); ++i)
  53. {
  54. data[i] = random.GetRandom();
  55. }
  56. for (size_t i = 0; i < DrawItemCountMax; ++i)
  57. {
  58. m_drawItemDatas.emplace_back(random, m_bufferEmpty.get(), m_psoEmpty.get());
  59. }
  60. m_indexBufferView = RHI::DeviceIndexBufferView(*m_bufferEmpty, random.GetRandom(), random.GetRandom(), RHI::IndexFormat::Uint16);
  61. }
  62. void ValidateDrawItem(const DrawItemData& drawItemData, RHI::DeviceDrawItemProperties itemProperties) const
  63. {
  64. const RHI::DeviceDrawItem* drawItem = itemProperties.m_item;
  65. EXPECT_EQ(itemProperties.m_sortKey, drawItemData.m_sortKey);
  66. EXPECT_EQ(drawItem->m_stencilRef, drawItemData.m_stencilRef);
  67. EXPECT_EQ(drawItem->m_pipelineState, drawItemData.m_pipelineState);
  68. EXPECT_EQ(static_cast<size_t>(drawItem->m_streamBufferViewCount), drawItemData.m_streamBufferViews.size());
  69. for (size_t i = 0; i < static_cast<size_t>(drawItem->m_streamBufferViewCount); ++i)
  70. {
  71. EXPECT_EQ(drawItemData.m_streamBufferViews[i].GetHash(), drawItem->m_streamBufferViews[i].GetHash());
  72. }
  73. EXPECT_EQ(static_cast<size_t>(drawItem->m_shaderResourceGroupCount), m_srgs.size());
  74. for (size_t i = 0; i < m_srgs.size(); ++i)
  75. {
  76. EXPECT_EQ(m_srgs[i], drawItem->m_shaderResourceGroups[i]);
  77. }
  78. EXPECT_EQ(static_cast<size_t>(drawItem->m_rootConstantSize), m_rootConstants.size());
  79. for (size_t i = 0; i < m_rootConstants.size(); ++i)
  80. {
  81. EXPECT_EQ(m_rootConstants[i], drawItem->m_rootConstants[i]);
  82. }
  83. EXPECT_EQ(drawItem->m_indexBufferView->GetHash(), m_indexBufferView.GetHash());
  84. }
  85. const RHI::DeviceDrawPacket* Build(RHI::DeviceDrawPacketBuilder& builder)
  86. {
  87. builder.Begin(nullptr);
  88. for (auto& srgPtr : m_srgs)
  89. {
  90. builder.AddShaderResourceGroup(srgPtr.get());
  91. }
  92. builder.SetRootConstants(m_rootConstants);
  93. builder.SetIndexBufferView(m_indexBufferView);
  94. RHI::DrawListMask drawListMask;
  95. for (size_t i = 0; i < DrawItemCountMax; ++i)
  96. {
  97. const DrawItemData& drawItemData = m_drawItemDatas[i];
  98. drawListMask[drawItemData.m_tag.GetIndex()] = true;
  99. RHI::DeviceDrawPacketBuilder::DeviceDrawRequest drawRequest;
  100. drawRequest.m_listTag = drawItemData.m_tag;
  101. drawRequest.m_sortKey = drawItemData.m_sortKey;
  102. drawRequest.m_stencilRef = drawItemData.m_stencilRef;
  103. drawRequest.m_streamBufferViews = drawItemData.m_streamBufferViews;
  104. drawRequest.m_pipelineState = drawItemData.m_pipelineState;
  105. builder.AddDrawItem(drawRequest);
  106. }
  107. const RHI::DeviceDrawPacket* drawPacket = builder.End();
  108. EXPECT_NE(drawPacket, nullptr);
  109. EXPECT_EQ(drawPacket->GetDrawListMask(), drawListMask);
  110. EXPECT_EQ(drawPacket->GetDrawItemCount(), m_drawItemDatas.size());
  111. for (size_t i = 0; i < m_drawItemDatas.size(); ++i)
  112. {
  113. ValidateDrawItem(m_drawItemDatas[i], drawPacket->GetDrawItemProperties(i));
  114. }
  115. return drawPacket;
  116. }
  117. RHI::Ptr<RHI::DeviceBuffer> m_bufferEmpty;
  118. RHI::ConstPtr<RHI::DevicePipelineState> m_psoEmpty;
  119. AZStd::array<RHI::Ptr<RHI::DeviceShaderResourceGroup>, RHI::Limits::Pipeline::ShaderResourceGroupCountMax> m_srgs;
  120. AZStd::array<uint8_t, sizeof(unsigned int) * 4> m_rootConstants;
  121. RHI::DeviceIndexBufferView m_indexBufferView;
  122. AZStd::vector<DrawItemData> m_drawItemDatas;
  123. };
  124. class DrawPacketTest
  125. : public RHITestFixture
  126. {
  127. protected:
  128. static const uint32_t s_randomSeed = 1234;
  129. RHI::Ptr<RHI::DrawListTagRegistry> m_drawListTagRegistry;
  130. RHI::DrawListContext m_drawListContext;
  131. AZStd::unique_ptr<AZ::RHI::RHISystem> m_rhiSystem;
  132. AZStd::unique_ptr<Factory> m_factory;
  133. public:
  134. void SetUp() override
  135. {
  136. RHITestFixture::SetUp();
  137. m_factory.reset(aznew Factory());
  138. m_drawListTagRegistry = RHI::DrawListTagRegistry::Create();
  139. m_rhiSystem.reset(aznew AZ::RHI::RHISystem);
  140. m_rhiSystem->InitDevices();
  141. m_rhiSystem->Init();
  142. }
  143. void TearDown() override
  144. {
  145. m_rhiSystem->Shutdown();
  146. m_rhiSystem.reset();
  147. m_drawListTagRegistry = nullptr;
  148. m_factory.reset();
  149. RHITestFixture::TearDown();
  150. }
  151. void TestDrawListTagRegistryNullCase()
  152. {
  153. RHI::DrawListTag nullTag = m_drawListTagRegistry->AcquireTag(Name());
  154. EXPECT_TRUE(nullTag.IsNull());
  155. EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0);
  156. m_drawListTagRegistry->ReleaseTag(nullTag);
  157. EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0);
  158. }
  159. void TestDrawListTagRegistrySimple()
  160. {
  161. const Name forwardName1("Forward");
  162. const Name forwardName2("forward");
  163. RHI::DrawListTag forwardTag1 = m_drawListTagRegistry->AcquireTag(forwardName1);
  164. RHI::DrawListTag forwardTag2 = m_drawListTagRegistry->AcquireTag(forwardName2);
  165. EXPECT_FALSE(forwardTag1.IsNull());
  166. EXPECT_FALSE(forwardTag2.IsNull());
  167. EXPECT_NE(forwardTag1, forwardTag2);
  168. RHI::DrawListTag forwardTag3 = m_drawListTagRegistry->AcquireTag(forwardName1);
  169. EXPECT_EQ(forwardTag1, forwardTag3);
  170. m_drawListTagRegistry->ReleaseTag(forwardTag1);
  171. m_drawListTagRegistry->ReleaseTag(forwardTag2);
  172. m_drawListTagRegistry->ReleaseTag(forwardTag3);
  173. EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0);
  174. }
  175. void TestDrawListTagRegistryDeAllocateAssert()
  176. {
  177. AZ_TEST_START_ASSERTTEST;
  178. EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0);
  179. const Name tagName{ "Test" };
  180. RHI::DrawListTag tag = m_drawListTagRegistry->AcquireTag(tagName);
  181. m_drawListTagRegistry->AcquireTag(tagName);
  182. m_drawListTagRegistry->AcquireTag(tagName);
  183. m_drawListTagRegistry->ReleaseTag(tag);
  184. m_drawListTagRegistry->ReleaseTag(tag);
  185. m_drawListTagRegistry->ReleaseTag(tag);
  186. // One additional forfeit should assert.
  187. m_drawListTagRegistry->ReleaseTag(tag);
  188. AZ_TEST_STOP_ASSERTTEST(1);
  189. }
  190. void TestDrawListTagRegistryRandomAllocations()
  191. {
  192. AZ::SimpleLcgRandom random(s_randomSeed);
  193. AZStd::vector<RHI::DrawListTag> acquiredTags;
  194. const uint32_t IterationCount = 1000;
  195. for (uint32_t iter = 0; iter < IterationCount; ++iter)
  196. {
  197. Name tagNameUnique = Name(AZStd::string::format("Tag_%d", iter));
  198. // Acquire
  199. if (random.GetRandom() % 2)
  200. {
  201. RHI::DrawListTag tag = m_drawListTagRegistry->AcquireTag(tagNameUnique);
  202. if (tag.IsNull())
  203. {
  204. EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), RHI::Limits::Pipeline::DrawListTagCountMax);
  205. }
  206. else
  207. {
  208. EXPECT_LT(m_drawListTagRegistry->GetAllocatedTagCount(), RHI::Limits::Pipeline::DrawListTagCountMax);
  209. acquiredTags.emplace_back(tag);
  210. }
  211. }
  212. // Forfeit
  213. else if (!acquiredTags.empty())
  214. {
  215. size_t tagIndex = random.GetRandom() % static_cast<uint32_t>(acquiredTags.size());
  216. RHI::DrawListTag tag = acquiredTags[tagIndex];
  217. size_t allocationCountBefore = m_drawListTagRegistry->GetAllocatedTagCount();
  218. m_drawListTagRegistry->ReleaseTag(tag);
  219. size_t allocationCountAfter = m_drawListTagRegistry->GetAllocatedTagCount();
  220. EXPECT_EQ(allocationCountBefore - allocationCountAfter, 1);
  221. acquiredTags.erase(acquiredTags.begin() + tagIndex);
  222. }
  223. EXPECT_EQ(acquiredTags.size(), m_drawListTagRegistry->GetAllocatedTagCount());
  224. }
  225. // Erase all references, make sure the registry is empty again.
  226. for (RHI::DrawListTag tag : acquiredTags)
  227. {
  228. m_drawListTagRegistry->ReleaseTag(tag);
  229. }
  230. acquiredTags.clear();
  231. EXPECT_EQ(m_drawListTagRegistry->GetAllocatedTagCount(), 0);
  232. }
  233. void DrawPacketEmpty()
  234. {
  235. RHI::DeviceDrawPacketBuilder builder;
  236. builder.Begin(nullptr);
  237. const RHI::DeviceDrawPacket* drawPacket = builder.End();
  238. EXPECT_EQ(drawPacket, nullptr);
  239. }
  240. void DrawPacketNullItem()
  241. {
  242. RHI::DeviceDrawPacketBuilder builder;
  243. builder.Begin(nullptr);
  244. RHI::DeviceDrawPacketBuilder::DeviceDrawRequest drawRequest;
  245. builder.AddDrawItem(drawRequest);
  246. const RHI::DeviceDrawPacket* drawPacket = builder.End();
  247. EXPECT_EQ(drawPacket, nullptr);
  248. }
  249. void DrawPacketBuild()
  250. {
  251. AZ::SimpleLcgRandom random(s_randomSeed);
  252. DrawPacketData drawPacketData(random);
  253. RHI::DeviceDrawPacketBuilder builder;
  254. const RHI::DeviceDrawPacket* drawPacket = drawPacketData.Build(builder);
  255. delete drawPacket;
  256. }
  257. void DrawPacketBuildClearBuildNull()
  258. {
  259. AZ::SimpleLcgRandom random(s_randomSeed);
  260. DrawPacketData drawPacketData(random);
  261. RHI::DeviceDrawPacketBuilder builder;
  262. const RHI::DeviceDrawPacket* drawPacket = drawPacketData.Build(builder);
  263. delete drawPacket;
  264. // Try to build a 'null' packet. This should result in a null pointer.
  265. builder.Begin(nullptr);
  266. drawPacket = builder.End();
  267. EXPECT_EQ(drawPacket, nullptr);
  268. }
  269. void DrawPacketClone()
  270. {
  271. AZ::SimpleLcgRandom random(s_randomSeed);
  272. DrawPacketData drawPacketData(random);
  273. RHI::DeviceDrawPacketBuilder builder;
  274. const RHI::DeviceDrawPacket* drawPacket = drawPacketData.Build(builder);
  275. RHI::DeviceDrawPacketBuilder builder2;
  276. const RHI::DeviceDrawPacket* drawPacketClone = builder2.Clone(drawPacket);
  277. EXPECT_EQ(drawPacket->m_drawItemCount, drawPacketClone->m_drawItemCount);
  278. EXPECT_EQ(drawPacket->m_streamBufferViewCount, drawPacketClone->m_streamBufferViewCount);
  279. EXPECT_EQ(drawPacket->m_shaderResourceGroupCount, drawPacketClone->m_shaderResourceGroupCount);
  280. EXPECT_EQ(drawPacket->m_uniqueShaderResourceGroupCount, drawPacketClone->m_uniqueShaderResourceGroupCount);
  281. EXPECT_EQ(drawPacket->m_rootConstantSize, drawPacketClone->m_rootConstantSize);
  282. EXPECT_EQ(drawPacket->m_scissorsCount, drawPacketClone->m_scissorsCount);
  283. EXPECT_EQ(drawPacket->m_viewportsCount, drawPacketClone->m_viewportsCount);
  284. uint8_t drawItemCount = drawPacket->m_drawItemCount;
  285. for (uint8_t i = 0; i < drawItemCount; ++i)
  286. {
  287. EXPECT_EQ(drawPacket->GetDrawListTag(i), drawPacketClone->GetDrawListTag(i));
  288. EXPECT_EQ(drawPacket->GetDrawFilterMask(i), drawPacketClone->GetDrawFilterMask(i));
  289. EXPECT_EQ(*(drawPacket->m_drawItemSortKeys + i), *(drawPacketClone->m_drawItemSortKeys + i));
  290. const RHI::DeviceDrawItem* drawItem = drawPacket->m_drawItems + i;
  291. const RHI::DeviceDrawItem* drawItemClone = drawPacketClone->m_drawItems + i;
  292. // Check the clone is an actual copy not an identical pointer.
  293. EXPECT_NE(drawItem, drawItemClone);
  294. EXPECT_EQ(drawItem->m_arguments.m_type, drawItemClone->m_arguments.m_type);
  295. EXPECT_EQ(drawItem->m_pipelineState->GetType(), drawItemClone->m_pipelineState->GetType());
  296. EXPECT_EQ(drawItem->m_stencilRef, drawItemClone->m_stencilRef);
  297. EXPECT_EQ(drawItem->m_streamBufferViewCount, drawItemClone->m_streamBufferViewCount);
  298. EXPECT_EQ(drawItem->m_shaderResourceGroupCount, drawItemClone->m_shaderResourceGroupCount);
  299. EXPECT_EQ(drawItem->m_rootConstantSize, drawItemClone->m_rootConstantSize);
  300. EXPECT_EQ(drawItem->m_scissorsCount, drawItemClone->m_scissorsCount);
  301. EXPECT_EQ(drawItem->m_viewportsCount, drawItemClone->m_viewportsCount);
  302. uint8_t streamBufferViewCount = drawItem->m_streamBufferViewCount;
  303. uint8_t shaderResourceGroupCount = drawItem->m_shaderResourceGroupCount;
  304. uint8_t rootConstantSize = drawItem->m_rootConstantSize;
  305. uint8_t scissorsCount = drawItem->m_scissorsCount;
  306. uint8_t viewportsCount = drawItem->m_viewportsCount;
  307. for (uint8_t j = 0; j < streamBufferViewCount; ++j)
  308. {
  309. const RHI::DeviceStreamBufferView* streamBufferView = drawPacket->m_streamBufferViews + j;
  310. const RHI::DeviceStreamBufferView* streamBufferViewClone = drawPacketClone->m_streamBufferViews + j;
  311. EXPECT_EQ(streamBufferView->GetByteCount(), streamBufferViewClone->GetByteCount());
  312. EXPECT_EQ(streamBufferView->GetByteOffset(), streamBufferViewClone->GetByteOffset());
  313. EXPECT_EQ(streamBufferView->GetByteStride(), streamBufferViewClone->GetByteStride());
  314. EXPECT_EQ(streamBufferView->GetHash(), streamBufferViewClone->GetHash());
  315. }
  316. for (uint8_t j = 0; j < shaderResourceGroupCount; ++j)
  317. {
  318. EXPECT_EQ(*(drawItem->m_shaderResourceGroups + j), *(drawItemClone->m_shaderResourceGroups + j));
  319. }
  320. for (uint8_t j = 0; j < rootConstantSize; ++j)
  321. {
  322. EXPECT_EQ(*(drawItem->m_rootConstants + j), *(drawItemClone->m_rootConstants + j));
  323. }
  324. for (uint8_t j = 0; j < scissorsCount; ++j)
  325. {
  326. EXPECT_EQ(drawItem->m_scissors + j, drawItemClone->m_scissors + j);
  327. }
  328. for (uint8_t j = 0; j < viewportsCount; ++j)
  329. {
  330. EXPECT_EQ(drawItem->m_viewports + j, drawItemClone->m_viewports + j);
  331. }
  332. }
  333. uint8_t streamBufferViewCount = drawPacket->m_streamBufferViewCount;
  334. uint8_t shaderResourceGroupCount = drawPacket->m_shaderResourceGroupCount;
  335. uint8_t uniqueShaderResourceGroupCount = drawPacket->m_uniqueShaderResourceGroupCount;
  336. uint8_t rootConstantSize = drawPacket->m_rootConstantSize;
  337. uint8_t scissorsCount = drawPacket->m_scissorsCount;
  338. uint8_t viewportsCount = drawPacket->m_viewportsCount;
  339. for (uint8_t i = 0; i < streamBufferViewCount; ++i)
  340. {
  341. const RHI::DeviceStreamBufferView* streamBufferView = drawPacket->m_streamBufferViews + i;
  342. const RHI::DeviceStreamBufferView* streamBufferViewClone = drawPacketClone->m_streamBufferViews + i;
  343. EXPECT_EQ(streamBufferView->GetByteCount(), streamBufferViewClone->GetByteCount());
  344. EXPECT_EQ(streamBufferView->GetByteOffset(), streamBufferViewClone->GetByteOffset());
  345. EXPECT_EQ(streamBufferView->GetByteStride(), streamBufferViewClone->GetByteStride());
  346. EXPECT_EQ(streamBufferView->GetHash(), streamBufferViewClone->GetHash());
  347. }
  348. for (uint8_t i = 0; i < shaderResourceGroupCount; ++i)
  349. {
  350. EXPECT_EQ(*(drawPacket->m_shaderResourceGroups + i), *(drawPacketClone->m_shaderResourceGroups + i));
  351. }
  352. for (uint8_t i = 0; i < uniqueShaderResourceGroupCount; ++i)
  353. {
  354. EXPECT_EQ(*(drawPacket->m_uniqueShaderResourceGroups + i), *(drawPacketClone->m_uniqueShaderResourceGroups + i));
  355. }
  356. for (uint8_t i = 0; i < rootConstantSize; ++i)
  357. {
  358. EXPECT_EQ(*(drawPacket->m_rootConstants + i), *(drawPacketClone->m_rootConstants + i));
  359. }
  360. for (uint8_t i = 0; i < scissorsCount; ++i)
  361. {
  362. EXPECT_EQ(drawPacket->m_scissors + i, drawPacketClone->m_scissors + i);
  363. }
  364. for (uint8_t i = 0; i < viewportsCount; ++i)
  365. {
  366. EXPECT_EQ(drawPacket->m_viewports + i, drawPacketClone->m_viewports + i);
  367. }
  368. delete drawPacket;
  369. delete drawPacketClone;
  370. }
  371. void TestSetInstanceCount()
  372. {
  373. AZ::SimpleLcgRandom random(s_randomSeed);
  374. DrawPacketData drawPacketData(random);
  375. RHI::DeviceDrawPacketBuilder builder;
  376. const RHI::DeviceDrawPacket* drawPacket = drawPacketData.Build(builder);
  377. RHI::DeviceDrawPacketBuilder builder2;
  378. RHI::DeviceDrawPacket* drawPacketClone = const_cast<RHI::DeviceDrawPacket*>(builder2.Clone(drawPacket));
  379. uint8_t drawItemCount = drawPacketClone->m_drawItemCount;
  380. // Test default value
  381. for (uint8_t i = 0; i < drawItemCount; ++i)
  382. {
  383. const RHI::DeviceDrawItem* drawItemClone = drawPacketClone->m_drawItems + i;
  384. EXPECT_EQ(drawItemClone->m_arguments.m_type, RHI::DrawType::Indexed);
  385. EXPECT_EQ(drawItemClone->m_arguments.m_indexed.m_instanceCount, 1);
  386. }
  387. drawPacketClone->SetInstanceCount(12);
  388. for (uint8_t i = 0; i < drawItemCount; ++i)
  389. {
  390. const RHI::DeviceDrawItem* drawItemClone = drawPacketClone->m_drawItems + i;
  391. EXPECT_EQ(drawItemClone->m_arguments.m_indexed.m_instanceCount, 12);
  392. // Check that the original draw packet is not affected
  393. const RHI::DeviceDrawItem* drawItem = drawPacket->m_drawItems + i;
  394. EXPECT_EQ(drawItem->m_arguments.m_indexed.m_instanceCount, 1);
  395. }
  396. delete drawPacket;
  397. delete drawPacketClone;
  398. }
  399. void TestSetRootConstants()
  400. {
  401. AZ::SimpleLcgRandom random(s_randomSeed);
  402. DrawPacketData drawPacketData(random);
  403. RHI::DeviceDrawPacketBuilder builder;
  404. const RHI::DeviceDrawPacket* drawPacket = drawPacketData.Build(builder);
  405. RHI::DeviceDrawPacketBuilder builder2;
  406. RHI::DeviceDrawPacket* drawPacketClone = const_cast<RHI::DeviceDrawPacket*>(builder2.Clone(drawPacket));
  407. AZStd::array<uint8_t, sizeof(unsigned int) * 4> rootConstantOld;
  408. EXPECT_EQ(sizeof(unsigned int) * 4, drawPacketClone->m_rootConstantSize);
  409. // Keep a copy of old root constant for later verification
  410. for (uint8_t i = 0; i < drawPacketClone->m_rootConstantSize; ++i)
  411. {
  412. rootConstantOld[i] = drawPacketClone->m_rootConstants[i];
  413. }
  414. // Root constant data to be set, partial size as of the full root constant size.
  415. AZStd::array<uint8_t, sizeof(unsigned int) * 2> rootConstantNew = { 1, 2, 3, 4, 5, 6, 7, 8 };
  416. // Attempt to set beyond the array
  417. AZ_TEST_START_TRACE_SUPPRESSION;
  418. drawPacketClone->SetRootConstant(9, rootConstantNew);
  419. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  420. // Nothing will be set if it triggers the assert
  421. for (uint8_t i = 0; i < drawPacketClone->m_rootConstantSize; ++i)
  422. {
  423. EXPECT_EQ(rootConstantOld[i], drawPacketClone->m_rootConstants[i]);
  424. }
  425. drawPacketClone->SetRootConstant(8, rootConstantNew);
  426. // Compare the part staying the same.
  427. for (uint8_t i = 0; i < drawPacketClone->m_rootConstantSize - 8; ++i)
  428. {
  429. EXPECT_EQ(rootConstantOld[i], drawPacketClone->m_rootConstants[i]);
  430. }
  431. // Compare the part being set
  432. for (uint8_t i = drawPacketClone->m_rootConstantSize - 8; i < drawPacketClone->m_rootConstantSize; ++i)
  433. {
  434. EXPECT_EQ(rootConstantNew[i - (drawPacketClone->m_rootConstantSize - 8)], drawPacketClone->m_rootConstants[i]);
  435. }
  436. // Compare the origin which shouldn't be affected.
  437. for (uint8_t i = 0; i < drawPacket->m_rootConstantSize; ++i)
  438. {
  439. EXPECT_EQ(rootConstantOld[i], drawPacket->m_rootConstants[i]);
  440. }
  441. delete drawPacket;
  442. delete drawPacketClone;
  443. }
  444. };
  445. TEST_F(DrawPacketTest, TestDrawListTagRegistryNullCase)
  446. {
  447. TestDrawListTagRegistryNullCase();
  448. }
  449. TEST_F(DrawPacketTest, TestDrawListTagRegistrySimple)
  450. {
  451. TestDrawListTagRegistrySimple();
  452. }
  453. TEST_F(DrawPacketTest, TestDrawListTagRegistryDeAllocateAssert)
  454. {
  455. TestDrawListTagRegistryDeAllocateAssert();
  456. }
  457. TEST_F(DrawPacketTest, TestDrawListTagRegistryRandomAllocations)
  458. {
  459. TestDrawListTagRegistryRandomAllocations();
  460. }
  461. TEST_F(DrawPacketTest, DrawPacketEmpty)
  462. {
  463. DrawPacketEmpty();
  464. }
  465. TEST_F(DrawPacketTest, DrawPacketNullItem)
  466. {
  467. DrawPacketNullItem();
  468. }
  469. TEST_F(DrawPacketTest, DrawPacketBuild)
  470. {
  471. DrawPacketBuild();
  472. }
  473. TEST_F(DrawPacketTest, DrawPacketBuildClearBuildNull)
  474. {
  475. DrawPacketBuildClearBuildNull();
  476. }
  477. TEST_F(DrawPacketTest, DrawPacketClone)
  478. {
  479. DrawPacketClone();
  480. }
  481. TEST_F(DrawPacketTest, TestSetInstanceCount)
  482. {
  483. TestSetInstanceCount();
  484. }
  485. TEST_F(DrawPacketTest, TestSetRootConstants)
  486. {
  487. TestSetRootConstants();
  488. }
  489. }
  490. AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);