BasicRHIComponent.cpp 25 KB

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