FrameGraphTests.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  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 <Tests/FrameGraph.h>
  10. #include <Tests/Factory.h>
  11. #include <Tests/Device.h>
  12. #include <Atom/RHI/ImagePool.h>
  13. #include <Atom/RHI/BufferPool.h>
  14. #include <Atom/RHI/ImageFrameAttachment.h>
  15. #include <Atom/RHI/BufferFrameAttachment.h>
  16. #include <Atom/RHI/ImageScopeAttachment.h>
  17. #include <Atom/RHI/BufferScopeAttachment.h>
  18. #include <AzCore/Math/Random.h>
  19. namespace UnitTest
  20. {
  21. using namespace AZ;
  22. class FrameGraphTests
  23. : public RHITestFixture
  24. {
  25. public:
  26. FrameGraphTests()
  27. : RHITestFixture()
  28. {
  29. }
  30. void ValidateBinding(
  31. const RHI::Scope* scope,
  32. const RHI::BufferScopeAttachment* scopeAttachment,
  33. const RHI::Buffer* buffer)
  34. {
  35. ASSERT_TRUE(scopeAttachment->GetPrevious() == nullptr);
  36. ASSERT_TRUE(scopeAttachment->GetNext() == nullptr);
  37. ASSERT_TRUE(&scopeAttachment->GetScope() == scope);
  38. const RHI::BufferFrameAttachment& attachment = scopeAttachment->GetFrameAttachment();
  39. ASSERT_TRUE(attachment.GetFirstScope(scope->GetDeviceIndex()) == scope);
  40. ASSERT_TRUE(attachment.GetLastScope(scope->GetDeviceIndex()) == scope);
  41. ASSERT_TRUE(attachment.GetFirstScopeAttachment(scope->GetDeviceIndex()) == scopeAttachment);
  42. ASSERT_TRUE(attachment.GetLastScopeAttachment(scope->GetDeviceIndex()) == scopeAttachment);
  43. if (buffer)
  44. {
  45. ASSERT_TRUE(buffer == attachment.GetBuffer());
  46. }
  47. }
  48. void ValidateBinding(
  49. const RHI::Scope* scope,
  50. const RHI::ImageScopeAttachment* scopeAttachment,
  51. const RHI::Image* image)
  52. {
  53. ASSERT_TRUE(scopeAttachment->GetPrevious() == nullptr);
  54. ASSERT_TRUE(scopeAttachment->GetNext() == nullptr);
  55. ASSERT_TRUE(&scopeAttachment->GetScope() == scope);
  56. const RHI::ImageFrameAttachment& attachment = scopeAttachment->GetFrameAttachment();
  57. ASSERT_TRUE(attachment.GetFirstScope(scope->GetDeviceIndex()) == scope);
  58. ASSERT_TRUE(attachment.GetLastScope(scope->GetDeviceIndex()) == scope);
  59. ASSERT_TRUE(attachment.GetFirstScopeAttachment(scope->GetDeviceIndex()) == scopeAttachment);
  60. ASSERT_TRUE(attachment.GetLastScopeAttachment(scope->GetDeviceIndex()) == scopeAttachment);
  61. if (image)
  62. {
  63. ASSERT_TRUE(image == attachment.GetImage());
  64. }
  65. }
  66. void SetUp() override
  67. {
  68. RHITestFixture::SetUp();
  69. m_rootFactory.reset(aznew Factory());
  70. m_rhiSystem.reset(aznew AZ::RHI::RHISystem);
  71. m_rhiSystem->InitDevices();
  72. m_rhiSystem->Init();
  73. m_state.reset(new State);
  74. {
  75. m_state->m_bufferPool = aznew RHI::BufferPool;
  76. RHI::BufferPoolDescriptor desc;
  77. desc.m_bindFlags = RHI::BufferBindFlags::ShaderReadWrite;
  78. desc.m_deviceMask = RHI::MultiDevice::DefaultDevice;
  79. m_state->m_bufferPool->Init(desc);
  80. }
  81. for (uint32_t i = 0; i < BufferCount; ++i)
  82. {
  83. RHI::Ptr<RHI::Buffer> buffer;
  84. buffer = aznew RHI::Buffer;
  85. RHI::BufferDescriptor desc;
  86. desc.m_bindFlags = RHI::BufferBindFlags::ShaderReadWrite;
  87. desc.m_byteCount = BufferSize;
  88. RHI::BufferInitRequest request;
  89. request.m_descriptor = desc;
  90. request.m_buffer = buffer.get();
  91. m_state->m_bufferPool->InitBuffer(request);
  92. AZStd::string name = AZStd::string::format("B%d", i);
  93. m_state->m_bufferAttachments[i].m_id = RHI::AttachmentId(name);
  94. m_state->m_bufferAttachments[i].m_buffer = AZStd::move(buffer);
  95. }
  96. {
  97. m_state->m_imagePool = aznew RHI::ImagePool;
  98. RHI::ImagePoolDescriptor desc;
  99. desc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite;
  100. desc.m_deviceMask = RHI::MultiDevice::DefaultDevice;
  101. m_state->m_imagePool->Init(desc);
  102. }
  103. for (uint32_t i = 0; i < ImageCount; ++i)
  104. {
  105. RHI::Ptr<RHI::Image> image;
  106. image = aznew RHI::Image;
  107. RHI::ImageDescriptor desc = RHI::ImageDescriptor::Create2D(
  108. RHI::ImageBindFlags::ShaderReadWrite,
  109. ImageSize,
  110. ImageSize,
  111. RHI::Format::R8G8B8A8_UNORM);
  112. desc.m_mipLevels = ImageMipCount;
  113. desc.m_arraySize = ImageArrayCount;
  114. RHI::ImageInitRequest request;
  115. request.m_descriptor = desc;
  116. request.m_image = image.get();
  117. m_state->m_imagePool->InitImage(request);
  118. m_state->m_imageAttachments[i].m_id = RHI::AttachmentId(AZStd::string::format("I%d", i));
  119. m_state->m_imageAttachments[i].m_image = AZStd::move(image);
  120. }
  121. for (uint32_t i = 0; i < ScopeCount; ++i)
  122. {
  123. RHI::Ptr<RHI::Scope> scope;
  124. scope = RHI::Factory::Get().CreateScope();
  125. scope->Init(RHI::ScopeId{AZStd::string::format("S%d", i)});
  126. m_state->m_scopes[i] = AZStd::move(scope);
  127. }
  128. m_state->m_frameGraphCompiler = RHI::Factory::Get().CreateFrameGraphCompiler();
  129. m_state->m_frameGraphCompiler->Init();
  130. }
  131. void TearDown() override
  132. {
  133. m_state.reset();
  134. m_rhiSystem->Shutdown();
  135. m_rhiSystem.reset();
  136. m_rootFactory.reset();
  137. RHITestFixture::TearDown();
  138. }
  139. void TestEmptyGraph()
  140. {
  141. RHI::FrameGraph frameGraph;
  142. for (uint32_t frameIdx = 0; frameIdx < FrameIterationCount; ++frameIdx)
  143. {
  144. /// Test an empty graph.
  145. frameGraph.Begin();
  146. frameGraph.End();
  147. {
  148. RHI::FrameGraphCompileRequest request;
  149. request.m_frameGraph = &frameGraph;
  150. m_state->m_frameGraphCompiler->Compile(request);
  151. }
  152. ASSERT_TRUE(frameGraph.GetScopes().empty());
  153. }
  154. }
  155. void TestSingleEmptyScope()
  156. {
  157. RHI::FrameGraph frameGraph;
  158. for (uint32_t frameIdx = 0; frameIdx < FrameIterationCount; ++frameIdx)
  159. {
  160. frameGraph.Begin();
  161. frameGraph.BeginScope(*m_state->m_scopes[0]);
  162. frameGraph.EndScope();
  163. frameGraph.End();
  164. {
  165. RHI::FrameGraphCompileRequest request;
  166. request.m_frameGraph = &frameGraph;
  167. m_state->m_frameGraphCompiler->Compile(request);
  168. }
  169. ASSERT_TRUE(frameGraph.GetScopes().size() == 1);
  170. ASSERT_TRUE(frameGraph.GetScopes()[0] == m_state->m_scopes[0]);
  171. }
  172. }
  173. void TestSingleScope()
  174. {
  175. RHI::FrameGraph frameGraph;
  176. for (uint32_t frameIdx = 0; frameIdx < FrameIterationCount; ++frameIdx)
  177. {
  178. frameGraph.Begin();
  179. frameGraph.BeginScope(*m_state->m_scopes[0]);
  180. frameGraph.SetHardwareQueueClass(RHI::HardwareQueueClass::Graphics);
  181. frameGraph.GetAttachmentDatabase().ImportBuffer(m_state->m_bufferAttachments[0].m_id, m_state->m_bufferAttachments[0].m_buffer);
  182. frameGraph.GetAttachmentDatabase().ImportBuffer(m_state->m_bufferAttachments[1].m_id, m_state->m_bufferAttachments[1].m_buffer);
  183. {
  184. RHI::BufferScopeAttachmentDescriptor desc;
  185. desc.m_attachmentId = m_state->m_bufferAttachments[0].m_id;
  186. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize);
  187. desc.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Clear;
  188. desc.m_loadStoreAction.m_clearValue = RHI::ClearValue::CreateVector4Float(1.0f, 0.0, 0.0, 0.0);
  189. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  190. desc.m_attachmentId = m_state->m_bufferAttachments[1].m_id;
  191. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  192. }
  193. frameGraph.GetAttachmentDatabase().ImportImage(m_state->m_imageAttachments[0].m_id, m_state->m_imageAttachments[0].m_image);
  194. frameGraph.GetAttachmentDatabase().ImportImage(m_state->m_imageAttachments[1].m_id, m_state->m_imageAttachments[1].m_image);
  195. frameGraph.GetAttachmentDatabase().ImportImage(m_state->m_imageAttachments[2].m_id, m_state->m_imageAttachments[2].m_image);
  196. {
  197. RHI::ImageScopeAttachmentDescriptor desc;
  198. desc.m_attachmentId = m_state->m_imageAttachments[0].m_id;
  199. desc.m_loadStoreAction.m_clearValue = RHI::ClearValue::CreateVector4Float(0.0f, 1.0f, 0.0f, 1.0f);
  200. desc.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Clear;
  201. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor();
  202. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  203. desc.m_attachmentId = m_state->m_imageAttachments[1].m_id;
  204. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  205. desc.m_attachmentId = m_state->m_imageAttachments[2].m_id;
  206. AZ_TEST_START_TRACE_SUPPRESSION;
  207. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::Uninitialized);
  208. AZ_TEST_STOP_TRACE_SUPPRESSION(1);
  209. }
  210. const RHI::FrameGraphAttachmentDatabase& attachmentDatabase = frameGraph.GetAttachmentDatabase();
  211. ASSERT_TRUE(attachmentDatabase.GetAttachments().size() == 5);
  212. ASSERT_TRUE(attachmentDatabase.GetBufferDescriptor(m_state->m_bufferAttachments[0].m_id).GetHash() == m_state->m_bufferAttachments[0].m_buffer->GetDescriptor().GetHash());
  213. ASSERT_TRUE(attachmentDatabase.GetBufferDescriptor(m_state->m_bufferAttachments[1].m_id).GetHash() == m_state->m_bufferAttachments[1].m_buffer->GetDescriptor().GetHash());
  214. ASSERT_TRUE(attachmentDatabase.GetImageDescriptor(m_state->m_imageAttachments[0].m_id).GetHash() == m_state->m_imageAttachments[0].m_image->GetDescriptor().GetHash());
  215. ASSERT_TRUE(attachmentDatabase.GetImageDescriptor(m_state->m_imageAttachments[1].m_id).GetHash() == m_state->m_imageAttachments[1].m_image->GetDescriptor().GetHash());
  216. frameGraph.EndScope();
  217. frameGraph.End();
  218. {
  219. RHI::FrameGraphCompileRequest request;
  220. request.m_frameGraph = &frameGraph;
  221. m_state->m_frameGraphCompiler->Compile(request);
  222. }
  223. ASSERT_TRUE(frameGraph.GetScopes().size() == 1);
  224. ASSERT_TRUE(frameGraph.GetScopes()[0] == m_state->m_scopes[0]);
  225. const RHI::Scope* scope = frameGraph.FindScope(m_state->m_scopes[0]->GetId());
  226. ASSERT_TRUE(scope == m_state->m_scopes[0].get());
  227. ASSERT_TRUE(scope->GetIndex() == 0);
  228. ASSERT_TRUE(scope->GetBufferAttachments().size() == 2);
  229. for (uint32_t i = 0; i < 2; ++i)
  230. {
  231. ValidateBinding(scope, scope->GetBufferAttachments()[i], m_state->m_bufferAttachments[i].m_buffer.get());
  232. }
  233. ASSERT_TRUE(scope->GetImageAttachments().size() == 3);
  234. ASSERT_TRUE(scope->GetAttachments().size() == 5);
  235. for (uint32_t i = 0; i < 2; ++i)
  236. {
  237. ValidateBinding(scope, scope->GetImageAttachments()[i], m_state->m_imageAttachments[i].m_image.get());
  238. }
  239. }
  240. }
  241. void TestScopeGraph()
  242. {
  243. RHI::FrameGraph frameGraph;
  244. RHI::ImageScopeAttachmentDescriptor imageBindingDescs[2];
  245. imageBindingDescs[0].m_imageViewDescriptor = RHI::ImageViewDescriptor();
  246. imageBindingDescs[0].m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Clear;
  247. imageBindingDescs[0].m_loadStoreAction.m_clearValue = RHI::ClearValue::CreateVector4Float(1.0f, 0.0, 0.0, 0.0);
  248. imageBindingDescs[1] = imageBindingDescs[0];
  249. imageBindingDescs[1].m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Load;
  250. RHI::BufferScopeAttachmentDescriptor bufferBindingDescs[2];
  251. bufferBindingDescs[0].m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize);
  252. bufferBindingDescs[0].m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Clear;
  253. bufferBindingDescs[0].m_loadStoreAction.m_clearValue = RHI::ClearValue::CreateVector4Float(1.0f, 0.0, 0.0, 0.0);
  254. bufferBindingDescs[1] = bufferBindingDescs[0];
  255. bufferBindingDescs[1].m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Load;
  256. AZ::SimpleLcgRandom random;
  257. struct Interval
  258. {
  259. uint32_t m_begin;
  260. uint32_t m_end;
  261. };
  262. for (uint32_t frameIdx = 0; frameIdx < FrameIterationCount; ++frameIdx)
  263. {
  264. frameGraph.Begin();
  265. Interval bufferScopeIntervals[BufferCount];
  266. for (uint32_t i = 0; i < BufferCount; ++i)
  267. {
  268. uint32_t b = random.GetRandom() % ScopeCount;
  269. uint32_t e = random.GetRandom() % ScopeCount;
  270. if (b > e)
  271. {
  272. AZStd::swap(b, e);
  273. }
  274. bufferScopeIntervals[i].m_begin = b;
  275. bufferScopeIntervals[i].m_end = e;
  276. }
  277. Interval imageScopeIntervals[ImageCount];
  278. for (uint32_t i = 0; i < ImageCount; ++i)
  279. {
  280. uint32_t b = random.GetRandom() % ScopeCount;
  281. uint32_t e = random.GetRandom() % ScopeCount;
  282. if (b > e)
  283. {
  284. AZStd::swap(b, e);
  285. }
  286. imageScopeIntervals[i].m_begin = b;
  287. imageScopeIntervals[i].m_end = e;
  288. }
  289. for (uint32_t scopeIdx = 0; scopeIdx < ScopeCount; ++scopeIdx)
  290. {
  291. if (scopeIdx == 0)
  292. {
  293. for (uint32_t i = 0; i < BufferCount; ++i)
  294. {
  295. frameGraph.GetAttachmentDatabase().ImportBuffer(m_state->m_bufferAttachments[i].m_id, m_state->m_bufferAttachments[i].m_buffer);
  296. }
  297. for (uint32_t i = 0; i < ImageCount; ++i)
  298. {
  299. frameGraph.GetAttachmentDatabase().ImportImage(m_state->m_imageAttachments[i].m_id, m_state->m_imageAttachments[i].m_image);
  300. }
  301. }
  302. frameGraph.BeginScope(*m_state->m_scopes[scopeIdx]);
  303. for (uint32_t i = 0; i < BufferCount; ++i)
  304. {
  305. if (scopeIdx == bufferScopeIntervals[i].m_begin)
  306. {
  307. bufferBindingDescs[0].m_attachmentId = m_state->m_bufferAttachments[i].m_id;
  308. frameGraph.UseShaderAttachment(
  309. bufferBindingDescs[0], RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  310. }
  311. else if (scopeIdx == bufferScopeIntervals[i].m_end)
  312. {
  313. bufferBindingDescs[1].m_attachmentId = m_state->m_bufferAttachments[i].m_id;
  314. frameGraph.UseShaderAttachment(
  315. bufferBindingDescs[1], RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::AnyGraphics);
  316. }
  317. }
  318. for (uint32_t i = 0; i < ImageCount; ++i)
  319. {
  320. if (scopeIdx == imageScopeIntervals[i].m_begin)
  321. {
  322. imageBindingDescs[0].m_attachmentId = m_state->m_imageAttachments[i].m_id;
  323. frameGraph.UseShaderAttachment(
  324. imageBindingDescs[0], RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  325. }
  326. else if (scopeIdx == imageScopeIntervals[i].m_end)
  327. {
  328. imageBindingDescs[1].m_attachmentId = m_state->m_imageAttachments[i].m_id;
  329. frameGraph.UseShaderAttachment(
  330. imageBindingDescs[1], RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::AnyGraphics);
  331. }
  332. }
  333. frameGraph.EndScope();
  334. }
  335. frameGraph.End();
  336. {
  337. RHI::FrameGraphCompileRequest request;
  338. request.m_frameGraph = &frameGraph;
  339. m_state->m_frameGraphCompiler->Compile(request);
  340. }
  341. const RHI::FrameGraphAttachmentDatabase& attachmentDatabase = frameGraph.GetAttachmentDatabase();
  342. ASSERT_TRUE(frameGraph.GetScopes().size() == ScopeCount);
  343. ASSERT_TRUE(attachmentDatabase.GetAttachments().size() == BufferCount + ImageCount);
  344. ASSERT_TRUE(attachmentDatabase.GetBufferAttachments().size() == BufferCount);
  345. ASSERT_TRUE(attachmentDatabase.GetImageAttachments().size() == ImageCount);
  346. ASSERT_TRUE(attachmentDatabase.GetImportedImageAttachments().size() == ImageCount);
  347. ASSERT_TRUE(attachmentDatabase.GetImportedBufferAttachments().size() == BufferCount);
  348. for (uint32_t i = 0; i < ImageCount; ++i)
  349. {
  350. ASSERT_TRUE(attachmentDatabase.FindAttachment(m_state->m_imageAttachments[i].m_id) != nullptr);
  351. }
  352. for (uint32_t i = 0; i < BufferCount; ++i)
  353. {
  354. ASSERT_TRUE(attachmentDatabase.FindAttachment(m_state->m_bufferAttachments[i].m_id) != nullptr);
  355. }
  356. for (const RHI::FrameAttachment* attachment : attachmentDatabase.GetAttachments())
  357. {
  358. const RHI::ScopeAttachment* scopeAttachmentPrev = nullptr;
  359. for (const RHI::ScopeAttachment* scopeAttachment =
  360. attachment->GetFirstScopeAttachment(RHI::MultiDevice::DefaultDeviceIndex);
  361. scopeAttachment;
  362. scopeAttachment = scopeAttachment->GetNext())
  363. {
  364. ASSERT_TRUE(&scopeAttachment->GetFrameAttachment() == attachment);
  365. ASSERT_TRUE(scopeAttachment->GetPrevious() == scopeAttachmentPrev);
  366. if (scopeAttachmentPrev)
  367. {
  368. ASSERT_TRUE(scopeAttachmentPrev->GetScope().GetIndex() < scopeAttachment->GetScope().GetIndex());
  369. }
  370. scopeAttachmentPrev = scopeAttachment;
  371. }
  372. }
  373. }
  374. }
  375. void TestOverlappingAttachments()
  376. {
  377. RHI::FrameGraph frameGraph;
  378. for (uint32_t frameIdx = 0; frameIdx < FrameIterationCount; ++frameIdx)
  379. {
  380. frameGraph.Begin();
  381. frameGraph.BeginScope(*m_state->m_scopes[0]);
  382. frameGraph.SetHardwareQueueClass(RHI::HardwareQueueClass::Graphics);
  383. constexpr uint32_t numBufferImports = 6;
  384. for (uint32_t i = 0; i < numBufferImports; ++i)
  385. {
  386. frameGraph.GetAttachmentDatabase().ImportBuffer(
  387. m_state->m_bufferAttachments[i].m_id, m_state->m_bufferAttachments[i].m_buffer);
  388. }
  389. {
  390. // Same attachment added twice
  391. RHI::BufferScopeAttachmentDescriptor desc;
  392. desc.m_attachmentId = m_state->m_bufferAttachments[0].m_id;
  393. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize);
  394. desc.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::DontCare;
  395. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  396. AZ_TEST_START_TRACE_SUPPRESSION;
  397. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  398. AZ_TEST_STOP_ASSERTTEST(1);
  399. // Partial overlap
  400. desc.m_attachmentId = m_state->m_bufferAttachments[1].m_id;
  401. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize);
  402. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  403. desc.m_bufferViewDescriptor.m_elementOffset = 0;
  404. desc.m_bufferViewDescriptor.m_elementCount = 1;
  405. AZ_TEST_START_TRACE_SUPPRESSION;
  406. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  407. AZ_TEST_STOP_ASSERTTEST(1);
  408. // Edge overlap
  409. desc.m_attachmentId = m_state->m_bufferAttachments[2].m_id;
  410. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize/2);
  411. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  412. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw((BufferSize / 2) - 1, BufferSize);
  413. AZ_TEST_START_TRACE_SUPPRESSION;
  414. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  415. AZ_TEST_STOP_ASSERTTEST(1);
  416. // No overlap
  417. desc.m_attachmentId = m_state->m_bufferAttachments[3].m_id;
  418. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize/2);
  419. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  420. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw((BufferSize / 2) + 1, BufferSize);
  421. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  422. // Overlap read only
  423. desc.m_attachmentId = m_state->m_bufferAttachments[4].m_id;
  424. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize / 2);
  425. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::AnyGraphics);
  426. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw((BufferSize / 2) - 1, BufferSize);
  427. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::AnyGraphics);
  428. // Overlap with invalid usage
  429. desc.m_attachmentId = m_state->m_bufferAttachments[5].m_id;
  430. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize);
  431. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::AnyGraphics);
  432. desc.m_bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, BufferSize);
  433. AZ_TEST_START_TRACE_SUPPRESSION;
  434. frameGraph.UseAttachment(
  435. desc,
  436. RHI::ScopeAttachmentAccess::Read,
  437. RHI::ScopeAttachmentUsage::InputAssembly,
  438. RHI::ScopeAttachmentStage::VertexInput);
  439. AZ_TEST_STOP_ASSERTTEST(1);
  440. }
  441. constexpr uint32_t numImageImports = 9;
  442. for (uint32_t i = 0; i < numImageImports; ++i)
  443. {
  444. frameGraph.GetAttachmentDatabase().ImportImage(
  445. m_state->m_imageAttachments[i].m_id, m_state->m_imageAttachments[i].m_image);
  446. }
  447. {
  448. // Same attachment twice
  449. RHI::ImageScopeAttachmentDescriptor desc;
  450. desc.m_attachmentId = m_state->m_imageAttachments[0].m_id;
  451. desc.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::DontCare;
  452. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor();
  453. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  454. AZ_TEST_START_TRACE_SUPPRESSION;
  455. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  456. AZ_TEST_STOP_ASSERTTEST(1);
  457. // Mipmap overlap
  458. desc.m_attachmentId = m_state->m_imageAttachments[1].m_id;
  459. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 0, 1);
  460. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  461. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 1, 2);
  462. AZ_TEST_START_TRACE_SUPPRESSION;
  463. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  464. AZ_TEST_STOP_ASSERTTEST(1);
  465. // Mipmap overlap, Slice Overlap
  466. desc.m_attachmentId = m_state->m_imageAttachments[2].m_id;
  467. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 0, 1, 0, 1);
  468. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  469. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 1, 2, 1, 2);
  470. AZ_TEST_START_TRACE_SUPPRESSION;
  471. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  472. AZ_TEST_STOP_ASSERTTEST(1);
  473. // No overlap, different aspect mask
  474. desc.m_attachmentId = m_state->m_imageAttachments[3].m_id;
  475. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor();
  476. desc.m_imageViewDescriptor.m_aspectFlags = RHI::ImageAspectFlags::Depth;
  477. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  478. desc.m_imageViewDescriptor.m_aspectFlags = RHI::ImageAspectFlags::Stencil;
  479. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  480. // No overlap on mimap
  481. desc.m_attachmentId = m_state->m_imageAttachments[4].m_id;
  482. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 0, 1, 0, 1);
  483. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  484. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 2, 3, 0, 1);
  485. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  486. // No overlap on slice
  487. desc.m_attachmentId = m_state->m_imageAttachments[5].m_id;
  488. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 0, 1, 0, 1);
  489. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  490. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 0, 1, 2, 3);
  491. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  492. // No overlap on mipmap and slice
  493. desc.m_attachmentId = m_state->m_imageAttachments[6].m_id;
  494. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 0, 1, 1, 2);
  495. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  496. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::Unknown, 2, 3, 3, 4);
  497. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  498. // Overlap read only
  499. desc.m_attachmentId = m_state->m_imageAttachments[7].m_id;
  500. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor();
  501. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::AnyGraphics);
  502. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::AnyGraphics);
  503. // Overlap invalid usage
  504. desc.m_attachmentId = m_state->m_imageAttachments[8].m_id;
  505. desc.m_imageViewDescriptor = RHI::ImageViewDescriptor();
  506. frameGraph.UseDepthStencilAttachment(
  507. desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::EarlyFragmentTest);
  508. AZ_TEST_START_TRACE_SUPPRESSION;
  509. frameGraph.UseDepthStencilAttachment(
  510. desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::EarlyFragmentTest);
  511. AZ_TEST_STOP_ASSERTTEST(1);
  512. }
  513. frameGraph.EndScope();
  514. frameGraph.End();
  515. }
  516. }
  517. private:
  518. static const uint32_t FrameIterationCount = 32;
  519. static const uint32_t ImageCount = 256;
  520. static const uint32_t BufferCount = 256;
  521. static const uint32_t BufferSize = 64;
  522. static const uint32_t ImageSize = 16;
  523. static const uint32_t ImageMipCount = 5;
  524. static const uint32_t ImageArrayCount = 3;
  525. static const uint32_t ScopeCount = 128;
  526. AZStd::unique_ptr<AZ::RHI::RHISystem> m_rhiSystem;
  527. AZStd::unique_ptr<Factory> m_rootFactory;
  528. struct ImageAttachment
  529. {
  530. RHI::Ptr<RHI::Image> m_image;
  531. RHI::AttachmentId m_id;
  532. };
  533. struct BufferAttachment
  534. {
  535. RHI::Ptr<RHI::Buffer> m_buffer;
  536. RHI::AttachmentId m_id;
  537. };
  538. struct State
  539. {
  540. RHI::Ptr<RHI::BufferPool> m_bufferPool;
  541. RHI::Ptr<RHI::ImagePool> m_imagePool;
  542. RHI::Ptr<RHI::FrameGraphCompiler> m_frameGraphCompiler;
  543. ImageAttachment m_imageAttachments[ImageCount];
  544. BufferAttachment m_bufferAttachments[BufferCount];
  545. RHI::Ptr<RHI::Scope> m_scopes[ScopeCount];
  546. };
  547. AZStd::unique_ptr<State> m_state;
  548. };
  549. TEST_F(FrameGraphTests, TestEmptyGraph)
  550. {
  551. TestEmptyGraph();
  552. }
  553. TEST_F(FrameGraphTests, TestSingleEmptyScope)
  554. {
  555. TestSingleEmptyScope();
  556. }
  557. TEST_F(FrameGraphTests, TestSingleScope)
  558. {
  559. TestSingleScope();
  560. }
  561. TEST_F(FrameGraphTests, TestScopeGraph)
  562. {
  563. TestScopeGraph();
  564. }
  565. TEST_F(FrameGraphTests, TestOverlappingAttachments)
  566. {
  567. TestOverlappingAttachments();
  568. }
  569. }