3
0

ShaderResourceGroupBufferTests.cpp 26 KB

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