BasicRHIComponent.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  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 <RHI/BasicRHIComponent.h>
  9. #include <SampleComponentConfig.h>
  10. #include <Atom/Utils/AssetCollectionAsyncLoader.h>
  11. namespace AtomSampleViewer
  12. {
  13. AZ::RPI::Ptr<RHISamplePass> RHISamplePass::Create(const AZ::RPI::PassDescriptor& descriptor)
  14. {
  15. AZ::RPI::Ptr<RHISamplePass> pass = aznew RHISamplePass(descriptor);
  16. return AZStd::move(pass);
  17. }
  18. RHISamplePass::RHISamplePass(const AZ::RPI::PassDescriptor& descriptor)
  19. : AZ::RPI::RenderPass(descriptor)
  20. {
  21. m_flags.m_hasPipelineViewTag = true;
  22. m_pipelineViewTag = "MainCamera";
  23. }
  24. RHISamplePass::~RHISamplePass()
  25. {
  26. m_rhiSample = nullptr;
  27. }
  28. const AZ::RPI::PipelineViewTag& RHISamplePass::GetPipelineViewTag() const
  29. {
  30. return m_pipelineViewTag;
  31. }
  32. void RHISamplePass::SetRHISample(BasicRHIComponent* sample)
  33. {
  34. m_rhiSample = sample;
  35. if (m_rhiSample)
  36. {
  37. m_rhiSample->SetOutputInfo(m_outputAttachment->m_descriptor.m_image.m_size.m_width
  38. , m_outputAttachment->m_descriptor.m_image.m_size.m_height
  39. , m_outputAttachment->m_descriptor.m_image.m_format
  40. , m_outputAttachment->GetAttachmentId());
  41. }
  42. }
  43. void RHISamplePass::BuildInternal()
  44. {
  45. Base::BuildInternal();
  46. // The RHISamplePass template should have one owned image attachment which is the render target
  47. m_outputAttachment = m_ownedAttachments[0];
  48. // Force update pass attachment to get correct size and save it to local variables
  49. m_outputAttachment->Update();
  50. // update output info for the rhi sample
  51. if (m_rhiSample)
  52. {
  53. SetRHISample(m_rhiSample);
  54. }
  55. }
  56. void RHISamplePass::FrameBeginInternal(FramePrepareParams params)
  57. {
  58. // Note: we can't preview the output attachment of this pass properly
  59. // Ideally, we should import RHISamplePass's scope producer first, then rhi sample's scope producers
  60. // then add readback scope and preview copy scope.
  61. // We can't do it since some of them private to RenderPass which we can't access here.
  62. // Import this pass's scope producer
  63. Base::FrameBeginInternal(params);
  64. // Import sample's scope producer
  65. if (m_rhiSample)
  66. {
  67. auto frameGraphBuilder = params.m_frameGraphBuilder;
  68. m_rhiSample->FrameBeginInternal(*frameGraphBuilder);
  69. for (AZStd::shared_ptr<AZ::RHI::ScopeProducer>& producer : m_rhiSample->m_scopeProducers)
  70. {
  71. frameGraphBuilder->ImportScopeProducer(*producer);
  72. }
  73. }
  74. }
  75. uint32_t RHISamplePass::GetViewIndex() const
  76. {
  77. return m_viewIndex;
  78. }
  79. void RHISamplePass::SetViewIndex(const uint32_t viewIndex)
  80. {
  81. m_viewIndex = viewIndex;
  82. }
  83. bool BasicRHIComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
  84. {
  85. using namespace AZ;
  86. const auto config = azrtti_cast<const SampleComponentConfig*>(baseConfig);
  87. if (config != nullptr && config->m_windowContext)
  88. {
  89. m_windowContext = config->m_windowContext;
  90. return true;
  91. }
  92. return false;
  93. }
  94. void BasicRHIComponent::OnFramePrepare(AZ::RHI::FrameGraphBuilder& frameGraphBuilder)
  95. {
  96. // Check the swap chain since the system may still tick one more frame when window is closed and swapchain got destroied.
  97. if (!IsSupportedRHISamplePipeline() && m_windowContext->GetSwapChain())
  98. {
  99. SetOutputInfoFromWindowContext();
  100. FrameBeginInternal(frameGraphBuilder);
  101. for (AZStd::shared_ptr<AZ::RHI::ScopeProducer>& producer : m_scopeProducers)
  102. {
  103. frameGraphBuilder.ImportScopeProducer(*producer);
  104. }
  105. }
  106. }
  107. void BasicRHIComponent::SetVertexPosition(VertexPosition* positionBuffer, int bufferIndex, float x, float y, float z)
  108. {
  109. positionBuffer[bufferIndex].m_position[0] = x;
  110. positionBuffer[bufferIndex].m_position[1] = y;
  111. positionBuffer[bufferIndex].m_position[2] = z;
  112. }
  113. void BasicRHIComponent::SetVertexPosition(VertexPosition* positionBuffer, int bufferIndex, const AZ::Vector3& position)
  114. {
  115. positionBuffer[bufferIndex].m_position[0] = position.GetX();
  116. positionBuffer[bufferIndex].m_position[1] = position.GetY();
  117. positionBuffer[bufferIndex].m_position[2] = position.GetZ();
  118. }
  119. void BasicRHIComponent::SetVertexPosition(VertexPosition* positionBuffer, int bufferIndex, const VertexPosition& position)
  120. {
  121. positionBuffer[bufferIndex].m_position[0] = position.m_position[0];
  122. positionBuffer[bufferIndex].m_position[1] = position.m_position[1];
  123. positionBuffer[bufferIndex].m_position[2] = position.m_position[2];
  124. }
  125. void BasicRHIComponent::SetVertexColor(VertexColor* colorBuffer, int bufferIndex, float r, float g, float b, float a)
  126. {
  127. colorBuffer[bufferIndex].m_color[0] = r;
  128. colorBuffer[bufferIndex].m_color[1] = g;
  129. colorBuffer[bufferIndex].m_color[2] = b;
  130. colorBuffer[bufferIndex].m_color[3] = a;
  131. }
  132. void BasicRHIComponent::SetVertexColor(VertexColor* colorBuffer, int bufferIndex, const AZ::Vector4& color)
  133. {
  134. colorBuffer[bufferIndex].m_color[0] = color.GetX();
  135. colorBuffer[bufferIndex].m_color[1] = color.GetY();
  136. colorBuffer[bufferIndex].m_color[2] = color.GetZ();
  137. colorBuffer[bufferIndex].m_color[3] = color.GetW();
  138. }
  139. void BasicRHIComponent::SetVertexColor(VertexColor* colorBuffer, int bufferIndex, const VertexColor& color)
  140. {
  141. colorBuffer[bufferIndex].m_color[0] = color.m_color[0];
  142. colorBuffer[bufferIndex].m_color[1] = color.m_color[1];
  143. colorBuffer[bufferIndex].m_color[2] = color.m_color[2];
  144. colorBuffer[bufferIndex].m_color[3] = color.m_color[3];
  145. }
  146. void BasicRHIComponent::SetVertexIndex(uint16_t* indexBuffer, int bufferIndex, const uint16_t index)
  147. {
  148. indexBuffer[bufferIndex] = index;
  149. }
  150. void BasicRHIComponent::SetVertexU(VertexU* uBuffer, int bufferIndex, float u)
  151. {
  152. uBuffer[bufferIndex].m_u = u;
  153. }
  154. void BasicRHIComponent::SetVertexUV(VertexUV* uvBuffer, int bufferIndex, float u, float v)
  155. {
  156. uvBuffer[bufferIndex].m_uv[0] = u;
  157. uvBuffer[bufferIndex].m_uv[1] = v;
  158. }
  159. void BasicRHIComponent::SetVertexUVW(VertexUVW* uvwBuffer, int bufferIndex, float u, float v, float w)
  160. {
  161. uvwBuffer[bufferIndex].m_uvw[0] = u;
  162. uvwBuffer[bufferIndex].m_uvw[1] = v;
  163. uvwBuffer[bufferIndex].m_uvw[2] = w;
  164. }
  165. void BasicRHIComponent::SetVertexUVW(VertexUVW* uvwBuffer, int bufferIndex, const AZ::Vector3& uvw)
  166. {
  167. uvwBuffer[bufferIndex].m_uvw[0] = uvw.GetX();
  168. uvwBuffer[bufferIndex].m_uvw[1] = uvw.GetY();
  169. uvwBuffer[bufferIndex].m_uvw[2] = uvw.GetZ();
  170. }
  171. void BasicRHIComponent::SetVertexUVWX(VertexUVWX* uvwxBuffer, int bufferIndex, float u, float v, float w, float x)
  172. {
  173. uvwxBuffer[bufferIndex].m_uvwx[0] = u;
  174. uvwxBuffer[bufferIndex].m_uvwx[1] = v;
  175. uvwxBuffer[bufferIndex].m_uvwx[2] = w;
  176. uvwxBuffer[bufferIndex].m_uvwx[3] = x;
  177. }
  178. void BasicRHIComponent::SetVertexNormal(VertexNormal* normalBuffer, int bufferIndex, float nx, float ny, float nz)
  179. {
  180. normalBuffer[bufferIndex].m_normal[0] = nx;
  181. normalBuffer[bufferIndex].m_normal[1] = ny;
  182. normalBuffer[bufferIndex].m_normal[2] = nz;
  183. }
  184. void BasicRHIComponent::SetVertexNormal(VertexNormal* normalBuffer, int bufferIndex, const AZ::Vector3& normal)
  185. {
  186. normalBuffer[bufferIndex].m_normal[0] = normal.GetX();
  187. normalBuffer[bufferIndex].m_normal[1] = normal.GetY();
  188. normalBuffer[bufferIndex].m_normal[2] = normal.GetZ();
  189. }
  190. void BasicRHIComponent::SetFullScreenRect(VertexPosition* positionBuffer, VertexUV* uvBuffer, uint16_t* indexBuffer)
  191. {
  192. SetVertexPosition(positionBuffer, 0, -1.0f, -1.0f, 0.0f);
  193. SetVertexPosition(positionBuffer, 1, -1.0f, 1.0f, 0.0f);
  194. SetVertexPosition(positionBuffer, 2, 1.0f, 1.0f, 0.0f);
  195. SetVertexPosition(positionBuffer, 3, 1.0f, -1.0f, 0.0f);
  196. if (uvBuffer)
  197. {
  198. SetVertexUV(uvBuffer, 0, 0.0f, 0.0f);
  199. SetVertexUV(uvBuffer, 1, 0.0f, 1.0f);
  200. SetVertexUV(uvBuffer, 2, 1.0f, 1.0f);
  201. SetVertexUV(uvBuffer, 3, 1.0f, 0.0f);
  202. }
  203. indexBuffer[0] = 0;
  204. indexBuffer[1] = 3;
  205. indexBuffer[2] = 1;
  206. indexBuffer[3] = 1;
  207. indexBuffer[4] = 3;
  208. indexBuffer[5] = 2;
  209. }
  210. void BasicRHIComponent::SetCube(VertexPosition* positionBuffer, VertexColor* colorBuffer, VertexNormal* normalBuffer, uint16_t* indexBuffer)
  211. {
  212. static AZ::Vector3 vertices[] =
  213. {
  214. //Front Face
  215. AZ::Vector3(1.0, 1.0, 1.0), AZ::Vector3(-1.0, 1.0, 1.0), AZ::Vector3(-1.0, -1.0, 1.0), AZ::Vector3(1.0, -1.0, 1.0),
  216. //Back Face
  217. AZ::Vector3(1.0, 1.0, -1.0), AZ::Vector3(-1.0, 1.0, -1.0), AZ::Vector3(-1.0, -1.0, -1.0), AZ::Vector3(1.0, -1.0, -1.0),
  218. //Left Face
  219. AZ::Vector3(-1.0, 1.0, 1.0), AZ::Vector3(-1.0, -1.0, 1.0), AZ::Vector3(-1.0, -1.0, -1.0), AZ::Vector3(-1.0, 1.0, -1.0),
  220. //Right Face
  221. AZ::Vector3(1.0, 1.0, 1.0), AZ::Vector3(1.0, -1.0, 1.0), AZ::Vector3(1.0, -1.0, -1.0), AZ::Vector3(1.0, 1.0, -1.0),
  222. //Top Face
  223. AZ::Vector3(1.0, 1.0, 1.0), AZ::Vector3(-1.0, 1.0, 1.0), AZ::Vector3(-1.0, 1.0, -1.0), AZ::Vector3(1.0, 1.0, -1.0),
  224. //Bottom Face
  225. AZ::Vector3(1.0, -1.0, 1.0), AZ::Vector3(-1.0, -1.0, 1.0), AZ::Vector3(-1.0, -1.0, -1.0), AZ::Vector3(1.0, -1.0, -1.0)
  226. };
  227. static AZ::Vector4 colors[] =
  228. {
  229. //Front Face
  230. AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0),
  231. //Back Face
  232. AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0),
  233. //Left Face
  234. AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0),
  235. //Right Face
  236. AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0),
  237. //Top Face
  238. AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0),
  239. //Bottom Face
  240. AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0), AZ::Vector4(0.0, 0.0, 1.0, 1.0)
  241. };
  242. static AZ::Vector3 normals[] =
  243. {
  244. //Front Face
  245. AZ::Vector3(0.0, 0.0, 1.0), AZ::Vector3(0.0, 0.0, 1.0), AZ::Vector3(0.0, 0.0, 1.0), AZ::Vector3(0.0, 0.0, 1.0),
  246. //Back Face
  247. AZ::Vector3(0.0, 0.0,-1.0), AZ::Vector3(0.0, 0.0,-1.0), AZ::Vector3(0.0, 0.0,-1.0), AZ::Vector3(0.0, 0.0,-1.0),
  248. //Left Face
  249. AZ::Vector3(-1.0, 0.0, 0.0), AZ::Vector3(-1.0, 0.0, 0.0), AZ::Vector3(-1.0, 0.0, 0.0), AZ::Vector3(-1.0, 0.0, 0.0),
  250. //Right Face
  251. AZ::Vector3(1.0, 0.0, 0.0), AZ::Vector3(1.0, 0.0, 0.0), AZ::Vector3(1.0, 0.0, 0.0), AZ::Vector3(1.0, 0.0, 0.0),
  252. //Top Face
  253. AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0), AZ::Vector3(0.0, 1.0, 0.0),
  254. //Bottom Face
  255. AZ::Vector3(0.0, -1.0, 0.0), AZ::Vector3(0.0, -1.0, 0.0), AZ::Vector3(0.0, -1.0, 0.0), AZ::Vector3(0.0, -1.0, 0.0)
  256. };
  257. static uint16_t indices[] =
  258. {
  259. //Back
  260. 2, 0, 1,
  261. 0, 2, 3,
  262. //Front
  263. 4, 6, 5,
  264. 6, 4, 7,
  265. //Left
  266. 8, 10, 9,
  267. 10, 8, 11,
  268. //Right
  269. 14, 12, 13,
  270. 15, 12, 14,
  271. //Top
  272. 16, 18, 17,
  273. 18, 16, 19,
  274. //Bottom
  275. 22, 20, 21,
  276. 23, 20, 22
  277. };
  278. for (int i = 0; i < AZ_ARRAY_SIZE(vertices); ++i)
  279. {
  280. SetVertexPosition(positionBuffer, i, vertices[i]);
  281. if (colorBuffer)
  282. {
  283. SetVertexColor(colorBuffer, i, colors[i]);
  284. }
  285. if (normalBuffer)
  286. {
  287. SetVertexNormal(normalBuffer, i, normals[i]);
  288. }
  289. }
  290. ::memcpy(indexBuffer, indices, sizeof(indices));
  291. }
  292. void BasicRHIComponent::SetVertexIndexIncreasing(uint16_t* indexBuffer, size_t bufferSize)
  293. {
  294. for (int i = 0; i < bufferSize; ++i)
  295. {
  296. indexBuffer[i] = static_cast<uint16_t>(i);
  297. }
  298. }
  299. AZ::Matrix4x4 BasicRHIComponent::CreateViewMatrix(AZ::Vector3 eye, AZ::Vector3 up, AZ::Vector3 lookAt)
  300. {
  301. AZ::Vector3 zaxis, xaxis, yaxis;
  302. zaxis = eye - lookAt;
  303. if (!zaxis.IsZero())
  304. {
  305. zaxis.Normalize();
  306. }
  307. xaxis = up.Cross(zaxis);
  308. if (!xaxis.IsZero())
  309. {
  310. xaxis.Normalize();
  311. }
  312. yaxis = zaxis.Cross(xaxis);
  313. AZ::Matrix4x4 result = AZ::Matrix4x4::CreateFromRows
  314. (
  315. AZ::Vector4(xaxis.GetX(), xaxis.GetY(), xaxis.GetZ(), -xaxis.Dot(eye)),
  316. AZ::Vector4(yaxis.GetX(), yaxis.GetY(), yaxis.GetZ(), -yaxis.Dot(eye)),
  317. AZ::Vector4(zaxis.GetX(), zaxis.GetY(), zaxis.GetZ(), -zaxis.Dot(eye)),
  318. AZ::Vector4( 0.f, 0.f, 0.f, 1.f)
  319. );
  320. return result;
  321. }
  322. void BasicRHIComponent::FindShaderInputIndex(
  323. AZ::RHI::ShaderInputConstantIndex* shaderInputConstIndex,
  324. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> shaderResourceGroup,
  325. const AZ::Name& shaderInputName,
  326. [[maybe_unused]] const char* componentName)
  327. {
  328. *shaderInputConstIndex = shaderResourceGroup->FindShaderInputConstantIndex(shaderInputName);
  329. AZ_Error(componentName, shaderInputConstIndex->IsValid(), "Failed to find shader input constant %s.", shaderInputName.GetCStr());
  330. }
  331. void BasicRHIComponent::FindShaderInputIndex(
  332. AZ::RHI::ShaderInputImageIndex* shaderInputImageIndex,
  333. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> shaderResourceGroup,
  334. const AZ::Name& shaderInputName,
  335. [[maybe_unused]] const char* componentName)
  336. {
  337. *shaderInputImageIndex = shaderResourceGroup->FindShaderInputImageIndex(shaderInputName);
  338. AZ_Error(componentName, shaderInputImageIndex->IsValid(), "Failed to find shader input image %s.", shaderInputName.GetCStr());
  339. }
  340. void BasicRHIComponent::FindShaderInputIndex(
  341. AZ::RHI::ShaderInputBufferIndex* shaderInputBufferIndex,
  342. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> shaderResourceGroup,
  343. const AZ::Name& shaderInputName,
  344. [[maybe_unused]] const char* componentName)
  345. {
  346. *shaderInputBufferIndex = shaderResourceGroup->FindShaderInputBufferIndex(shaderInputName);
  347. AZ_Error(componentName, shaderInputBufferIndex->IsValid(), "Failed to find shader input buffer %s.", shaderInputName.GetCStr());
  348. }
  349. void BasicRHIComponent::FindShaderInputIndex(
  350. AZ::RHI::ShaderInputSamplerIndex* shaderInputSamplerIndex,
  351. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> shaderResourceGroup,
  352. const AZ::Name& shaderInputName,
  353. [[maybe_unused]] const char* componentName)
  354. {
  355. *shaderInputSamplerIndex = shaderResourceGroup->FindShaderInputSamplerIndex(shaderInputName);
  356. AZ_Error(componentName, shaderInputSamplerIndex->IsValid(), "Failed to find sampler %s.", shaderInputName.GetCStr());
  357. }
  358. AZ::Data::Instance<AZ::RPI::Shader> BasicRHIComponent::LoadShader(const char* shaderFilePath, [[maybe_unused]] const char* sampleName, const AZ::Name* supervariantName)
  359. {
  360. using namespace AZ;
  361. Data::AssetId shaderAssetId;
  362. Data::AssetCatalogRequestBus::BroadcastResult(
  363. shaderAssetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
  364. shaderFilePath, azrtti_typeid<RPI::ShaderAsset>(), false);
  365. if (!shaderAssetId.IsValid())
  366. {
  367. AZ_Error(sampleName, false, "Failed to get shader asset id with path %s", shaderFilePath);
  368. return nullptr;
  369. }
  370. auto shaderAsset = Data::AssetManager::Instance().GetAsset<RPI::ShaderAsset>(
  371. shaderAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
  372. shaderAsset.BlockUntilLoadComplete();
  373. if (!shaderAsset.IsReady())
  374. {
  375. AZ_Error(sampleName, false, "Failed to get shader asset with path %s", shaderFilePath);
  376. return nullptr;
  377. }
  378. auto shader = RPI::Shader::FindOrCreate(shaderAsset, (supervariantName != nullptr) ? *supervariantName : AZ::Name{""});
  379. if (!shader)
  380. {
  381. AZ_Error(sampleName, false, "Failed to find or create a shader instance from shader asset '%s'", shaderFilePath);
  382. return nullptr;
  383. }
  384. return shader;
  385. }
  386. AZ::Data::Instance<AZ::RPI::Shader> BasicRHIComponent::LoadShader(const AZ::AssetCollectionAsyncLoader& assetLoadMgr, const char* shaderFilePath, [[maybe_unused]] const char* sampleName)
  387. {
  388. using namespace AZ;
  389. auto shaderAsset = assetLoadMgr.GetAsset<RPI::ShaderAsset>(shaderFilePath);
  390. AZ_Assert(shaderAsset.IsReady(), "Shader asset %s is supposed to be ready", shaderFilePath);
  391. auto shader = RPI::Shader::FindOrCreate(shaderAsset);
  392. if (!shader)
  393. {
  394. AZ_Error(sampleName, false, "Failed to find or create a shader instance from shader asset '%s'", shaderFilePath);
  395. return nullptr;
  396. }
  397. return shader;
  398. }
  399. AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> BasicRHIComponent::CreateShaderResourceGroup(AZ::Data::Instance<AZ::RPI::Shader> shader, const char* shaderResourceGroupId, [[maybe_unused]] const char* sampleName)
  400. {
  401. auto srg = AZ::RPI::ShaderResourceGroup::Create(shader->GetAsset(), shader->GetSupervariantIndex(), AZ::Name { shaderResourceGroupId });
  402. if (!srg)
  403. {
  404. AZ_Error(sampleName, false, "Failed to create shader resource group");
  405. return nullptr;
  406. }
  407. return srg;
  408. }
  409. AZ::Data::Instance<AZ::RPI::StreamingImage> BasicRHIComponent::LoadStreamingImage(const char* textureFilePath, [[maybe_unused]] const char* sampleName)
  410. {
  411. using namespace AZ;
  412. Data::AssetId streamingImageAssetId;
  413. Data::AssetCatalogRequestBus::BroadcastResult(
  414. streamingImageAssetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
  415. textureFilePath, azrtti_typeid<RPI::StreamingImageAsset>(), false);
  416. if (!streamingImageAssetId.IsValid())
  417. {
  418. AZ_Error(sampleName, false, "Failed to get streaming image asset id with path %s", textureFilePath);
  419. return nullptr;
  420. }
  421. auto streamingImageAsset = Data::AssetManager::Instance().GetAsset<RPI::StreamingImageAsset>(
  422. streamingImageAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
  423. streamingImageAsset.BlockUntilLoadComplete();
  424. if (!streamingImageAsset.IsReady())
  425. {
  426. AZ_Error(sampleName, false, "Failed to get streaming image asset '%s'", textureFilePath);
  427. return nullptr;
  428. }
  429. auto image = RPI::StreamingImage::FindOrCreate(streamingImageAsset);
  430. if (!image)
  431. {
  432. AZ_Error(sampleName, false, "Failed to find or create an image instance from image asset '%s'", textureFilePath);
  433. return nullptr;
  434. }
  435. return image;
  436. }
  437. void BasicRHIComponent::CreateImage3dData(AZStd::vector<uint8_t>& data, AZ::RHI::ImageSubresourceLayout& layout, AZ::RHI::Format& format, AZStd::vector<const char*>&& imageAssetPaths)
  438. {
  439. using namespace AZ;
  440. const auto getStreamingImageAsset = [](const char* path) -> AZ::Data::Asset<AZ::RPI::StreamingImageAsset>
  441. {
  442. Data::AssetId streamingImageAssetId;
  443. Data::AssetCatalogRequestBus::BroadcastResult(
  444. streamingImageAssetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
  445. path, azrtti_typeid<RPI::StreamingImageAsset>(), false);
  446. AZ::Data::Asset<AZ::RPI::StreamingImageAsset> streamingImageAsset = Data::AssetManager::Instance().GetAsset<RPI::StreamingImageAsset>(
  447. streamingImageAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
  448. streamingImageAsset.BlockUntilLoadComplete();
  449. return streamingImageAsset;
  450. };
  451. AZStd::vector<RHI::ImageDescriptor> imageDescriptors;
  452. imageDescriptors.reserve(imageAssetPaths.size());
  453. AZStd::vector<RHI::ImageSubresourceLayout> imageSubresourceLayouts;
  454. imageSubresourceLayouts.reserve(imageAssetPaths.size());
  455. AZStd::vector<Data::Asset<RPI::ImageMipChainAsset>> imageMipAssets;
  456. imageMipAssets.reserve(imageAssetPaths.size());
  457. // Load the first mip of the images
  458. for (const char* imageAssetPath : imageAssetPaths)
  459. {
  460. Data::Asset<AZ::RPI::StreamingImageAsset> streamingImageAsset = getStreamingImageAsset(imageAssetPath);
  461. RHI::ImageDescriptor imageDescriptor = streamingImageAsset->GetImageDescriptor();
  462. imageDescriptors.emplace_back(imageDescriptor);
  463. // Load the mip
  464. Data::Asset<RPI::ImageMipChainAsset> mipAsset = streamingImageAsset->GetMipChainAsset(0);
  465. mipAsset = Data::AssetManager::Instance().GetAsset<RPI::ImageMipChainAsset>(
  466. mipAsset.GetId(), AZ::Data::AssetLoadBehavior::PreLoad);
  467. mipAsset.BlockUntilLoadComplete();
  468. imageMipAssets.emplace_back(mipAsset);
  469. const RHI::ImageSubresourceLayout subImageLayout = mipAsset->GetSubImageLayout(0);
  470. imageSubresourceLayouts.emplace_back(subImageLayout);
  471. }
  472. // Validate the compatibility of the image sub resources
  473. for (uint32_t i = 1; i < imageSubresourceLayouts.size(); i++)
  474. {
  475. [[maybe_unused]] const bool compatibleFormat = imageDescriptors[0].m_format == imageDescriptors[i].m_format;
  476. [[maybe_unused]] const bool compatibleLayout = imageSubresourceLayouts[0].m_size == imageSubresourceLayouts[i].m_size &&
  477. imageSubresourceLayouts[0].m_rowCount == imageSubresourceLayouts[i].m_rowCount &&
  478. imageSubresourceLayouts[0].m_bytesPerRow == imageSubresourceLayouts[i].m_bytesPerRow &&
  479. imageSubresourceLayouts[0].m_bytesPerImage == imageSubresourceLayouts[i].m_bytesPerImage;
  480. AZ_Assert(compatibleLayout && compatibleFormat, "The image sub resources of the first MIP aren't compatible.");
  481. }
  482. // Allocate the data of the first mip of the images sequentially
  483. const uint32_t bytesPerImage = imageSubresourceLayouts[0].m_bytesPerImage;
  484. data.resize(imageSubresourceLayouts[0].m_bytesPerImage * imageSubresourceLayouts.size());
  485. for (uint32_t i = 0; i < imageMipAssets.size(); i++)
  486. {
  487. const uint64_t dataOffset = i * bytesPerImage;
  488. memcpy(static_cast<uint8_t*>(data.data()) + dataOffset, imageMipAssets[i]->GetSubImageData(0).data(), imageSubresourceLayouts[0].m_bytesPerImage);
  489. }
  490. format = imageDescriptors[0].m_format;
  491. layout = imageSubresourceLayouts[0];
  492. layout.m_size.m_depth = static_cast<uint32_t>(imageAssetPaths.size());
  493. }
  494. void BasicRHIComponent::SetOutputInfo(uint32_t width, uint32_t height, AZ::RHI::Format format, AZ::RHI::AttachmentId attachmentId)
  495. {
  496. m_outputWidth = width;
  497. m_outputHeight = height;
  498. m_outputFormat = format;
  499. m_outputAttachmentId = attachmentId;
  500. UpdateViewportAndScissor();
  501. }
  502. void BasicRHIComponent::SetOutputInfoFromWindowContext()
  503. {
  504. m_outputFormat = m_windowContext->GetSwapChain()->GetDescriptor().m_dimensions.m_imageFormat;
  505. m_outputWidth = aznumeric_cast<uint32_t>(m_windowContext->GetViewport().m_maxX - m_windowContext->GetViewport().m_minX);
  506. m_outputHeight = aznumeric_cast<uint32_t>(m_windowContext->GetViewport().m_maxY - m_windowContext->GetViewport().m_minY);
  507. m_outputAttachmentId = m_windowContext->GetSwapChain()->GetAttachmentId();
  508. UpdateViewportAndScissor();
  509. }
  510. void BasicRHIComponent::UpdateViewportAndScissor()
  511. {
  512. m_viewport = AZ::RHI::Viewport(0, aznumeric_cast<float>(m_outputWidth), 0, aznumeric_cast<float>(m_outputHeight));
  513. m_scissor = AZ::RHI::Scissor(0, 0, m_outputWidth, m_outputHeight);
  514. }
  515. bool BasicRHIComponent::IsSupportedRHISamplePipeline()
  516. {
  517. return m_supportRHISamplePipeline;
  518. }
  519. float BasicRHIComponent::GetViewportWidth()
  520. {
  521. return m_viewport.m_maxX - m_viewport.m_minX;
  522. }
  523. float BasicRHIComponent::GetViewportHeight()
  524. {
  525. return m_viewport.m_maxY - m_viewport.m_minY;
  526. }
  527. void BasicRHIComponent::SetViewIndex(const uint32_t viewIndex)
  528. {
  529. m_viewIndex = viewIndex;
  530. }
  531. }