ShaderResourceGroupBufferTests.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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/ShaderAssetTestUtils.h>
  11. #include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
  12. #include <Atom/RPI.Public/Buffer/Buffer.h>
  13. #include <Atom/RPI.Reflect/Buffer/BufferAssetCreator.h>
  14. #include <Atom/RPI.Reflect/ResourcePoolAssetCreator.h>
  15. namespace UnitTest
  16. {
  17. using namespace AZ;
  18. using namespace RPI;
  19. class ShaderResourceGroupBufferTests
  20. : public RPITestFixture
  21. {
  22. protected:
  23. Data::Asset<ShaderAsset> m_testSrgShaderAsset;
  24. RHI::Ptr<RHI::ShaderResourceGroupLayout> m_testSrgLayout;
  25. Data::Instance<ShaderResourceGroup> m_testSrg;
  26. Data::Asset<ResourcePoolAsset> m_bufferPoolAsset;
  27. Data::Asset<BufferAsset> m_shortBufferAsset;
  28. Data::Asset<BufferAsset> m_mediumBufferAsset;
  29. Data::Asset<BufferAsset> m_longBufferAsset;
  30. Data::Instance<Buffer> m_shortBuffer;
  31. Data::Instance<Buffer> m_mediumBuffer;
  32. Data::Instance<Buffer> m_longBuffer;
  33. Ptr<RHI::BufferView> m_bufferViewA;
  34. Ptr<RHI::BufferView> m_bufferViewB;
  35. Ptr<RHI::BufferView> m_bufferViewC;
  36. AZStd::vector<Data::Instance<Buffer>> m_threeBuffers;
  37. AZStd::vector<const RHI::BufferView*> m_threeBufferViews;
  38. const RHI::ShaderInputBufferIndex m_indexOfBufferA{ 0 };
  39. const RHI::ShaderInputBufferIndex m_indexOfBufferB{ 1 };
  40. const RHI::ShaderInputBufferIndex m_indexOfBufferArray{ 2 };
  41. const RHI::ShaderInputBufferIndex m_indexOfBufferInvalid{ 3 };
  42. RHI::Ptr<RHI::ShaderResourceGroupLayout> CreateTestSrgLayout(const char* nameId)
  43. {
  44. RHI::Ptr<RHI::ShaderResourceGroupLayout> srgLayout = RHI::ShaderResourceGroupLayout::Create();
  45. srgLayout->SetName(Name(nameId));
  46. srgLayout->SetBindingSlot(0);
  47. srgLayout->AddShaderInput(RHI::ShaderInputBufferDescriptor{ Name{ "MyBufferA" }, RHI::ShaderInputBufferAccess::Read, RHI::ShaderInputBufferType::Raw, 1, 4, 1, 1});
  48. srgLayout->AddShaderInput(RHI::ShaderInputBufferDescriptor{ Name{ "MyBufferB" }, RHI::ShaderInputBufferAccess::Read, RHI::ShaderInputBufferType::Raw, 1, 4, 2, 2});
  49. srgLayout->AddShaderInput(RHI::ShaderInputBufferDescriptor{ Name{ "MyBufferArray" }, RHI::ShaderInputBufferAccess::Read, RHI::ShaderInputBufferType::Raw, 3, 4, 3, 3});
  50. srgLayout->Finalize();
  51. return srgLayout;
  52. }
  53. Data::Asset<ResourcePoolAsset> CreateTestBufferPoolAsset()
  54. {
  55. Data::Asset<ResourcePoolAsset> asset;
  56. auto bufferPoolDesc = AZStd::make_unique<RHI::BufferPoolDescriptor>();
  57. bufferPoolDesc->m_bindFlags = RHI::BufferBindFlags::ShaderRead;
  58. bufferPoolDesc->m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
  59. ResourcePoolAssetCreator creator;
  60. creator.Begin(Uuid::CreateRandom());
  61. creator.SetPoolDescriptor(AZStd::move(bufferPoolDesc));
  62. creator.SetPoolName("TestPool");
  63. creator.End(asset);
  64. return asset;
  65. }
  66. Data::Asset<BufferAsset> CreateTestBufferAsset(const char* bufferStringContent)
  67. {
  68. const uint32_t bufferSize = static_cast<uint32_t>(strlen(bufferStringContent));
  69. Data::Asset<BufferAsset> asset;
  70. BufferAssetCreator bufferCreator;
  71. bufferCreator.Begin(Uuid::CreateRandom());
  72. bufferCreator.SetBuffer(bufferStringContent, bufferSize, RHI::BufferDescriptor{ RHI::BufferBindFlags::ShaderRead, bufferSize });
  73. bufferCreator.SetBufferViewDescriptor(RHI::BufferViewDescriptor::CreateRaw(0, bufferSize));
  74. bufferCreator.SetPoolAsset(m_bufferPoolAsset);
  75. bufferCreator.End(asset);
  76. return asset;
  77. }
  78. void SetUp() override
  79. {
  80. RPITestFixture::SetUp();
  81. m_testSrgLayout = CreateTestSrgLayout("TestSrg");
  82. m_testSrgShaderAsset = CreateTestShaderAsset(Uuid::CreateRandom(), m_testSrgLayout);
  83. m_testSrg = ShaderResourceGroup::Create(m_testSrgShaderAsset, AZ::RPI::DefaultSupervariantIndex, m_testSrgLayout->GetName());
  84. m_bufferPoolAsset = CreateTestBufferPoolAsset();
  85. m_shortBufferAsset = CreateTestBufferAsset("Short");
  86. m_mediumBufferAsset = CreateTestBufferAsset("Medium length buffer");
  87. m_longBufferAsset = CreateTestBufferAsset("This buffer is longer than the other two");
  88. m_shortBuffer = Buffer::FindOrCreate(m_shortBufferAsset);
  89. m_mediumBuffer = Buffer::FindOrCreate(m_mediumBufferAsset);
  90. m_longBuffer = Buffer::FindOrCreate(m_longBufferAsset);
  91. m_threeBuffers = { m_shortBuffer, m_mediumBuffer, m_longBuffer };
  92. m_bufferViewA = m_longBuffer->GetRHIBuffer()->GetBufferView(RHI::BufferViewDescriptor::CreateRaw(5, 6));
  93. m_bufferViewB = m_longBuffer->GetRHIBuffer()->GetBufferView(RHI::BufferViewDescriptor::CreateRaw(15, 4));
  94. m_bufferViewC = m_longBuffer->GetRHIBuffer()->GetBufferView(RHI::BufferViewDescriptor::CreateRaw(22, 18));
  95. m_threeBufferViews = { m_bufferViewA.get(), m_bufferViewB.get(), m_bufferViewC.get() };
  96. }
  97. void TearDown() override
  98. {
  99. m_testSrgLayout = nullptr;
  100. m_testSrg = nullptr;
  101. m_testSrgShaderAsset.Reset();
  102. m_shortBufferAsset.Reset();
  103. m_mediumBufferAsset.Reset();
  104. m_longBufferAsset.Reset();
  105. m_bufferPoolAsset.Reset();
  106. m_threeBuffers = AZStd::vector<Data::Instance<Buffer>>();
  107. m_threeBufferViews = AZStd::vector<const RHI::BufferView*>();
  108. m_bufferViewA = nullptr;
  109. m_bufferViewB = nullptr;
  110. m_bufferViewC = nullptr;
  111. m_shortBuffer = nullptr;
  112. m_mediumBuffer = nullptr;
  113. m_longBuffer = nullptr;
  114. RPITestFixture::TearDown();
  115. }
  116. };
  117. TEST_F(ShaderResourceGroupBufferTests, TestInvalidInputIndex)
  118. {
  119. // Test invalid indexes for all get/set functions
  120. const int bufferInvalidArrayOffset = 3;
  121. AZ_TEST_START_ASSERTTEST;
  122. // Buffers...
  123. EXPECT_FALSE(m_testSrg->SetBuffer(m_indexOfBufferInvalid, m_shortBuffer));
  124. EXPECT_FALSE(m_testSrg->GetBuffer(m_indexOfBufferInvalid));
  125. EXPECT_FALSE(m_testSrg->SetBuffer(m_indexOfBufferInvalid, m_shortBuffer, 1));
  126. EXPECT_FALSE(m_testSrg->SetBuffer(m_indexOfBufferArray, m_shortBuffer, bufferInvalidArrayOffset));
  127. EXPECT_FALSE(m_testSrg->GetBuffer(m_indexOfBufferInvalid, 1));
  128. EXPECT_FALSE(m_testSrg->GetBuffer(m_indexOfBufferArray, bufferInvalidArrayOffset));
  129. EXPECT_FALSE(m_testSrg->SetBufferArray(m_indexOfBufferInvalid, m_threeBuffers));
  130. EXPECT_FALSE(m_testSrg->SetBufferArray(m_indexOfBufferInvalid, m_threeBuffers, 0));
  131. EXPECT_EQ(0, m_testSrg->GetBufferArray(m_indexOfBufferInvalid).size());
  132. // Buffer Views...
  133. EXPECT_FALSE(m_testSrg->SetBufferView(m_indexOfBufferInvalid, m_bufferViewA.get()));
  134. EXPECT_FALSE(m_testSrg->GetBufferView(m_indexOfBufferInvalid));
  135. EXPECT_FALSE(m_testSrg->SetBufferView(m_indexOfBufferInvalid, m_bufferViewA.get(), 1));
  136. EXPECT_FALSE(m_testSrg->GetBufferView(m_indexOfBufferInvalid, 1));
  137. EXPECT_FALSE(m_testSrg->SetBufferView(m_indexOfBufferArray, m_bufferViewA.get(), bufferInvalidArrayOffset));
  138. EXPECT_FALSE(m_testSrg->GetBufferView(m_indexOfBufferArray, bufferInvalidArrayOffset));
  139. EXPECT_FALSE(m_testSrg->SetBufferViewArray(m_indexOfBufferInvalid, m_threeBufferViews));
  140. EXPECT_FALSE(m_testSrg->SetBufferViewArray(m_indexOfBufferInvalid, m_threeBufferViews, 0));
  141. EXPECT_EQ(0, m_testSrg->GetBufferViewArray(m_indexOfBufferInvalid).size());
  142. AZ_TEST_STOP_ASSERTTEST(18);
  143. }
  144. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBuffer)
  145. {
  146. // Test basic set/get operation...
  147. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferA, m_shortBuffer));
  148. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferB, m_mediumBuffer));
  149. EXPECT_EQ(m_shortBuffer, m_testSrg->GetBuffer(m_indexOfBufferA));
  150. EXPECT_EQ(m_mediumBuffer, m_testSrg->GetBuffer(m_indexOfBufferB));
  151. m_testSrg->Compile();
  152. EXPECT_EQ(m_shortBuffer->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferA, 0));
  153. EXPECT_EQ(m_mediumBuffer->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferB, 0));
  154. // Test changing back to null...
  155. ProcessQueuedSrgCompilations(m_testSrgShaderAsset, m_testSrgLayout->GetName());
  156. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferA, nullptr));
  157. m_testSrg->Compile();
  158. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferA));
  159. EXPECT_EQ(nullptr, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferA, 0));
  160. }
  161. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBufferAtOffset)
  162. {
  163. // Test basic set/get operation...
  164. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferArray, m_shortBuffer, 0));
  165. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferArray, m_mediumBuffer, 1));
  166. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferArray, m_longBuffer, 2));
  167. EXPECT_EQ(m_shortBuffer, m_testSrg->GetBuffer(m_indexOfBufferArray, 0));
  168. EXPECT_EQ(m_mediumBuffer, m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  169. EXPECT_EQ(m_longBuffer, m_testSrg->GetBuffer(m_indexOfBufferArray, 2));
  170. m_testSrg->Compile();
  171. EXPECT_EQ(m_shortBuffer->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 0));
  172. EXPECT_EQ(m_mediumBuffer->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 1));
  173. EXPECT_EQ(m_longBuffer->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 2));
  174. // Test changing back to null...
  175. ProcessQueuedSrgCompilations(m_testSrgShaderAsset, m_testSrgLayout->GetName());
  176. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferArray, nullptr, 1));
  177. m_testSrg->Compile();
  178. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  179. EXPECT_EQ(nullptr, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 1));
  180. }
  181. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBufferArray)
  182. {
  183. // Test basic set/get operation...
  184. EXPECT_TRUE(m_testSrg->SetBufferArray(m_indexOfBufferArray, m_threeBuffers));
  185. m_testSrg->Compile();
  186. EXPECT_EQ(3, m_testSrg->GetBufferArray(m_indexOfBufferArray).size());
  187. EXPECT_EQ(m_threeBuffers[0], m_testSrg->GetBufferArray(m_indexOfBufferArray)[0]);
  188. EXPECT_EQ(m_threeBuffers[1], m_testSrg->GetBufferArray(m_indexOfBufferArray)[1]);
  189. EXPECT_EQ(m_threeBuffers[2], m_testSrg->GetBufferArray(m_indexOfBufferArray)[2]);
  190. EXPECT_EQ(m_threeBuffers[0], m_testSrg->GetBuffer(m_indexOfBufferArray, 0));
  191. EXPECT_EQ(m_threeBuffers[1], m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  192. EXPECT_EQ(m_threeBuffers[2], m_testSrg->GetBuffer(m_indexOfBufferArray, 2));
  193. EXPECT_EQ(m_threeBuffers[0]->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 0));
  194. EXPECT_EQ(m_threeBuffers[1]->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 1));
  195. EXPECT_EQ(m_threeBuffers[2]->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 2));
  196. // Test replacing just two buffers including changing one buffer back to null...
  197. ProcessQueuedSrgCompilations(m_testSrgShaderAsset, m_testSrgLayout->GetName());
  198. AZStd::vector<Data::Instance<Buffer>> alternateBuffers = { m_mediumBuffer, nullptr };
  199. EXPECT_TRUE(m_testSrg->SetBufferArray(m_indexOfBufferArray, alternateBuffers));
  200. m_testSrg->Compile();
  201. EXPECT_TRUE(m_testSrg->GetBufferArray(m_indexOfBufferArray).size());
  202. EXPECT_EQ(m_mediumBuffer, m_testSrg->GetBuffer(m_indexOfBufferArray, 0));
  203. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  204. EXPECT_EQ(m_longBuffer, m_testSrg->GetBuffer(m_indexOfBufferArray, 2)); // remains unchanged
  205. }
  206. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBufferArray_ValidationFailure)
  207. {
  208. // Make sure the no changes are made when a validation failure is detected
  209. AZStd::vector<Data::Instance<Buffer>> tooManyBuffers{ 4, m_shortBuffer };
  210. AZ_TEST_START_ASSERTTEST;
  211. EXPECT_FALSE(m_testSrg->SetBufferArray(m_indexOfBufferArray, tooManyBuffers));
  212. AZ_TEST_STOP_ASSERTTEST(1);
  213. m_testSrg->Compile();
  214. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 0));
  215. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  216. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 2));
  217. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  218. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  219. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 2));
  220. }
  221. TEST_F(ShaderResourceGroupBufferTests, TestSetBufferArrayAtOffset)
  222. {
  223. AZStd::vector<Data::Instance<Buffer>> twoBuffers = { m_mediumBuffer, m_longBuffer };
  224. // Test set operation, skipping the first element...
  225. EXPECT_TRUE(m_testSrg->SetBufferArray(m_indexOfBufferArray, twoBuffers, 1));
  226. m_testSrg->Compile();
  227. EXPECT_EQ(3, m_testSrg->GetBufferArray(m_indexOfBufferArray).size());
  228. EXPECT_EQ(nullptr, m_testSrg->GetBufferArray(m_indexOfBufferArray)[0]);
  229. EXPECT_EQ(twoBuffers[0], m_testSrg->GetBufferArray(m_indexOfBufferArray)[1]);
  230. EXPECT_EQ(twoBuffers[1], m_testSrg->GetBufferArray(m_indexOfBufferArray)[2]);
  231. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 0));
  232. EXPECT_EQ(twoBuffers[0], m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  233. EXPECT_EQ(twoBuffers[1], m_testSrg->GetBuffer(m_indexOfBufferArray, 2));
  234. EXPECT_EQ(nullptr, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 0));
  235. EXPECT_EQ(twoBuffers[0]->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 1));
  236. EXPECT_EQ(twoBuffers[1]->GetBufferView(), m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 2));
  237. }
  238. TEST_F(ShaderResourceGroupBufferTests, TestSetBufferArrayAtOffset_ValidationFailure)
  239. {
  240. // Make sure the no changes are made when a validation failure is detected
  241. // 3 entries is too many because we will start at an offset of 1
  242. AZStd::vector<Data::Instance<Buffer>> tooManyBuffers{ 3, m_shortBuffer };
  243. AZ_TEST_START_ASSERTTEST;
  244. EXPECT_FALSE(m_testSrg->SetBufferArray(m_indexOfBufferArray, tooManyBuffers, 1));
  245. AZ_TEST_STOP_ASSERTTEST(1);
  246. m_testSrg->Compile();
  247. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 0));
  248. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  249. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 2));
  250. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  251. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  252. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 2));
  253. }
  254. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBufferView)
  255. {
  256. // Set some RPI::Buffers first, just to make sure these get cleared when setting an RPI::BufferView
  257. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferA, m_mediumBuffer));
  258. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferB, m_mediumBuffer));
  259. // Test valid set/get operation...
  260. EXPECT_TRUE(m_testSrg->SetBufferView(m_indexOfBufferA, m_bufferViewA.get()));
  261. EXPECT_TRUE(m_testSrg->SetBufferView(m_indexOfBufferB, m_bufferViewB.get()));
  262. m_testSrg->Compile();
  263. EXPECT_EQ(m_bufferViewA, m_testSrg->GetBufferView(m_indexOfBufferA));
  264. EXPECT_EQ(m_bufferViewB, m_testSrg->GetBufferView(m_indexOfBufferB));
  265. EXPECT_EQ(m_bufferViewA, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferA, 0));
  266. EXPECT_EQ(m_bufferViewB, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferB, 0));
  267. // The RPI::Buffer should get cleared when you set a RHI::BufferView directly
  268. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferA));
  269. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferB));
  270. }
  271. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBufferViewAtOffset)
  272. {
  273. // Set some RPI::Buffers first, just to make sure these get cleared when setting an RPI::BufferView
  274. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferArray, m_mediumBuffer, 0));
  275. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferArray, m_mediumBuffer, 1));
  276. EXPECT_TRUE(m_testSrg->SetBuffer(m_indexOfBufferArray, m_mediumBuffer, 2));
  277. // Test valid set/get operation...
  278. EXPECT_TRUE(m_testSrg->SetBufferView(m_indexOfBufferArray, m_bufferViewA.get(), 0));
  279. EXPECT_TRUE(m_testSrg->SetBufferView(m_indexOfBufferArray, m_bufferViewB.get(), 1));
  280. EXPECT_TRUE(m_testSrg->SetBufferView(m_indexOfBufferArray, m_bufferViewC.get(), 2));
  281. m_testSrg->Compile();
  282. EXPECT_EQ(m_bufferViewA, m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  283. EXPECT_EQ(m_bufferViewB, m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  284. EXPECT_EQ(m_bufferViewC, m_testSrg->GetBufferView(m_indexOfBufferArray, 2));
  285. EXPECT_EQ(m_bufferViewA, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 0));
  286. EXPECT_EQ(m_bufferViewB, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 1));
  287. EXPECT_EQ(m_bufferViewC, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 2));
  288. // The RPI::Buffer should get cleared when you set a RHI::BufferView directly
  289. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 0));
  290. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 1));
  291. EXPECT_EQ(nullptr, m_testSrg->GetBuffer(m_indexOfBufferArray, 2));
  292. }
  293. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBufferViewArray)
  294. {
  295. // Test basic set/get operation...
  296. EXPECT_TRUE(m_testSrg->SetBufferViewArray(m_indexOfBufferArray, m_threeBufferViews));
  297. m_testSrg->Compile();
  298. EXPECT_EQ(3, m_testSrg->GetBufferViewArray(m_indexOfBufferArray).size());
  299. EXPECT_EQ(m_threeBufferViews[0], m_testSrg->GetBufferViewArray(m_indexOfBufferArray)[0]);
  300. EXPECT_EQ(m_threeBufferViews[1], m_testSrg->GetBufferViewArray(m_indexOfBufferArray)[1]);
  301. EXPECT_EQ(m_threeBufferViews[2], m_testSrg->GetBufferViewArray(m_indexOfBufferArray)[2]);
  302. EXPECT_EQ(m_threeBufferViews[0], m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  303. EXPECT_EQ(m_threeBufferViews[1], m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  304. EXPECT_EQ(m_threeBufferViews[2], m_testSrg->GetBufferView(m_indexOfBufferArray, 2));
  305. EXPECT_EQ(m_threeBufferViews[0], m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 0));
  306. EXPECT_EQ(m_threeBufferViews[1], m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 1));
  307. EXPECT_EQ(m_threeBufferViews[2], m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 2));
  308. // Test replacing just two buffer views including changing one back to null...
  309. ProcessQueuedSrgCompilations(m_testSrgShaderAsset, m_testSrgLayout->GetName());
  310. AZStd::vector<const RHI::BufferView*> alternateBufferViews = { m_bufferViewB.get(), nullptr };
  311. EXPECT_TRUE(m_testSrg->SetBufferViewArray(m_indexOfBufferArray, alternateBufferViews));
  312. m_testSrg->Compile();
  313. EXPECT_EQ(m_bufferViewB, m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  314. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  315. EXPECT_EQ(m_bufferViewC, m_testSrg->GetBufferView(m_indexOfBufferArray, 2)); // remains unchanged
  316. }
  317. TEST_F(ShaderResourceGroupBufferTests, TestSetGetBufferViewArray_ValidationFailure)
  318. {
  319. // Make sure the no changes are made when a validation failure is detected
  320. AZStd::vector<const RHI::BufferView*> tooManyBufferViews{ 4, m_bufferViewA.get() };
  321. AZ_TEST_START_ASSERTTEST;
  322. EXPECT_FALSE(m_testSrg->SetBufferViewArray(m_indexOfBufferArray, tooManyBufferViews));
  323. AZ_TEST_STOP_ASSERTTEST(1);
  324. m_testSrg->Compile();
  325. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  326. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  327. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 2));
  328. }
  329. TEST_F(ShaderResourceGroupBufferTests, TestSetBufferViewArrayAtOffset)
  330. {
  331. AZStd::vector<const RHI::BufferView*> twoBufferViews = { m_bufferViewA.get(), m_bufferViewB.get() };
  332. // Test set operation, skipping the first element...
  333. EXPECT_TRUE(m_testSrg->SetBufferViewArray(m_indexOfBufferArray, twoBufferViews, 1));
  334. m_testSrg->Compile();
  335. EXPECT_EQ(3, m_testSrg->GetBufferViewArray(m_indexOfBufferArray).size());
  336. EXPECT_EQ(nullptr, m_testSrg->GetBufferViewArray(m_indexOfBufferArray)[0]);
  337. EXPECT_EQ(twoBufferViews[0], m_testSrg->GetBufferViewArray(m_indexOfBufferArray)[1]);
  338. EXPECT_EQ(twoBufferViews[1], m_testSrg->GetBufferViewArray(m_indexOfBufferArray)[2]);
  339. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  340. EXPECT_EQ(twoBufferViews[0], m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  341. EXPECT_EQ(twoBufferViews[1], m_testSrg->GetBufferView(m_indexOfBufferArray, 2));
  342. EXPECT_EQ(nullptr, m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 0));
  343. EXPECT_EQ(twoBufferViews[0], m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 1));
  344. EXPECT_EQ(twoBufferViews[1], m_testSrg->GetRHIShaderResourceGroup()->GetData().GetBufferView(m_indexOfBufferArray, 2));
  345. }
  346. TEST_F(ShaderResourceGroupBufferTests, TestSetBufferViewArrayAtOffset_ValidationFailure)
  347. {
  348. // Make sure the no changes are made when a validation failure is detected
  349. AZStd::vector<const RHI::BufferView*> tooManyBufferViews{ 3, m_bufferViewA.get() };
  350. AZ_TEST_START_ASSERTTEST;
  351. EXPECT_FALSE(m_testSrg->SetBufferViewArray(m_indexOfBufferArray, tooManyBufferViews, 1));
  352. AZ_TEST_STOP_ASSERTTEST(1);
  353. m_testSrg->Compile();
  354. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 0));
  355. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 1));
  356. EXPECT_EQ(nullptr, m_testSrg->GetBufferView(m_indexOfBufferArray, 2));
  357. }
  358. }