StreamBufferViewsBuilder.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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 "StreamBufferViewsBuilder.h"
  9. namespace AZ
  10. {
  11. namespace Render
  12. {
  13. class ShaderStreamBufferViews final : public ShaderStreamBufferViewsInterface
  14. {
  15. public:
  16. AZ_RTTI(
  17. AZ::Render::ShaderStreamBufferViews,
  18. "{35C88638-C8F8-4124-B7AD-269ED7BFE6BE}",
  19. AZ::Render::ShaderStreamBufferViewsInterface);
  20. ShaderStreamBufferViews() = delete;
  21. explicit ShaderStreamBufferViews(uint32_t lodIndex, uint32_t meshIndex)
  22. : m_lodIndex(lodIndex), m_meshIndex(meshIndex)
  23. {
  24. }
  25. ~ShaderStreamBufferViews() = default;
  26. ////////////////////////////////////////////////////////////
  27. // ShaderStreamBufferViewsInterface overrides Start...
  28. const AZ::RHI::Ptr<AZ::RHI::BufferView>& GetIndexBufferView() const override
  29. {
  30. return m_indexBufferView;
  31. }
  32. const AZ::RHI::Ptr<AZ::RHI::BufferView>& GetStreamBufferView(const AZ::RHI::ShaderSemantic& shaderSemantic) const override
  33. {
  34. static AZ::RHI::Ptr<AZ::RHI::BufferView> InvalidBufferView;
  35. if (!m_streamViewsBySemantic.contains(shaderSemantic))
  36. {
  37. return InvalidBufferView;
  38. }
  39. return m_streamViewsBySemantic.at(shaderSemantic);
  40. }
  41. const AZ::RHI::Ptr<AZ::RHI::BufferView>& GetStreamBufferView(const char* semanticName) const override
  42. {
  43. return GetStreamBufferView(AZ::RHI::ShaderSemantic::Parse(semanticName));
  44. }
  45. uint32_t GetLodIndex() const override
  46. {
  47. return m_lodIndex;
  48. }
  49. uint32_t GetMeshIndex() const override
  50. {
  51. return m_meshIndex;
  52. }
  53. // ShaderStreamBufferViewsInterface overrides End...
  54. ////////////////////////////////////////////////////////////
  55. private:
  56. friend class ShaderStreamBufferViewsBuilder;
  57. uint32_t m_lodIndex; //Kept for informational purposes.
  58. uint32_t m_meshIndex; //Kept for informational purposes.
  59. AZ::RHI::Ptr<AZ::RHI::BufferView> m_indexBufferView;
  60. using StreamBufferViewsBySemantic = AZStd::unordered_map<AZ::RHI::ShaderSemantic, AZ::RHI::Ptr<AZ::RHI::BufferView>>;
  61. StreamBufferViewsBySemantic m_streamViewsBySemantic;
  62. }; // class ShaderStreamBufferViews
  63. ShaderStreamBufferViewsBuilder::ShaderStreamBufferViewsBuilder(const AZ::Render::MeshFeatureProcessorInterface::MeshHandle& meshHandle)
  64. : m_meshHandle(&meshHandle)
  65. {
  66. }
  67. ////////////////////////////////////////////////////////////
  68. // StreamBufferViewsBuilderInterface overrides Start...
  69. bool ShaderStreamBufferViewsBuilder::AddStream(const char* semanticName, AZ::RHI::Format streamFormat, bool isOptional)
  70. {
  71. if (m_shaderInputContract)
  72. {
  73. AZ_Error(LogWindow, false, "Can not add stream '%s' because the ShaderInputContract was finalized!", semanticName);
  74. return false;
  75. }
  76. auto it = std::find_if(
  77. m_streamsList.cbegin(),
  78. m_streamsList.cend(),
  79. [semanticName](const StreamInfo& item) -> bool
  80. {
  81. return strcmp(item.m_semanticName, semanticName) == 0;
  82. });
  83. if (it != m_streamsList.end())
  84. {
  85. AZ_Error(LogWindow, false, "%s. A stream with name '%s' already exists!", __FUNCTION__, semanticName);
  86. return false;
  87. }
  88. m_streamsList.emplace_back(semanticName, streamFormat, isOptional);
  89. return true;
  90. }
  91. AZ::u8 ShaderStreamBufferViewsBuilder::GetStreamCount() const
  92. {
  93. return aznumeric_caster(m_streamsList.size());
  94. }
  95. AZStd::unique_ptr<ShaderStreamBufferViewsInterface> ShaderStreamBufferViewsBuilder::BuildShaderStreamBufferViews(
  96. uint32_t lodIndex, uint32_t meshIndex)
  97. {
  98. if (!m_shaderInputContract)
  99. {
  100. FinalizeShaderInputContract();
  101. }
  102. AZStd::unique_ptr<ShaderStreamBufferViews> shaderStreamBufferViews = AZStd::make_unique<ShaderStreamBufferViews>(lodIndex, meshIndex);
  103. const auto& modelInstance = (*m_meshHandle)->GetModel();
  104. if (!modelInstance)
  105. {
  106. // A valid MeshHandle, when the Mesh Asset is being loaded, may temporary not have a model instance.
  107. return shaderStreamBufferViews;
  108. }
  109. const auto& modelLods = modelInstance->GetLods();
  110. const auto& modelLod = modelLods[lodIndex];
  111. const auto& modelLodMeshList = modelLod->GetMeshes();
  112. const auto& modelLodMesh = modelLodMeshList[meshIndex];
  113. shaderStreamBufferViews->m_indexBufferView = BuildShaderIndexBufferView(modelLodMesh);
  114. // retrieve the material
  115. const AZ::Render::CustomMaterialId customMaterialId(lodIndex, modelLodMesh.m_materialSlotStableId);
  116. // This is a private function!
  117. const auto& customMaterialInfo = (*m_meshHandle)->GetCustomMaterialWithFallback(customMaterialId);
  118. const auto& material = customMaterialInfo.m_material ? customMaterialInfo.m_material : modelLodMesh.m_material;
  119. // retrieve vertex/index buffers
  120. AZ::RHI::InputStreamLayout inputStreamLayout;
  121. AZ::RHI::StreamBufferIndices streamIndices;
  122. [[maybe_unused]] bool result = modelLod->GetStreamsForMesh(
  123. inputStreamLayout,
  124. streamIndices,
  125. nullptr,
  126. *m_shaderInputContract.get(),
  127. meshIndex,
  128. customMaterialInfo.m_uvMapping,
  129. material->GetAsset()->GetMaterialTypeAsset()->GetUvNameMap());
  130. AZ_Assert(result, "Failed to retrieve mesh stream buffer views");
  131. const AZ::u8 streamCount = GetStreamCount();
  132. auto streamIter = modelLodMesh.CreateStreamIterator(streamIndices);
  133. auto streamChannels = inputStreamLayout.GetStreamChannels();
  134. for (AZ::u8 streamIdx = 0; streamIdx < streamCount; streamIdx++)
  135. {
  136. auto shaderSemantic = streamChannels[streamIdx].m_semantic;
  137. AZ::RHI::Buffer* rhiBuffer = const_cast<AZ::RHI::Buffer*>(streamIter[streamIdx].GetBuffer());
  138. uint32_t streamByteCount = static_cast<uint32_t>(rhiBuffer->GetDescriptor().m_byteCount);
  139. auto bufferViewDescriptor = AZ::RHI::BufferViewDescriptor::CreateRaw(0, streamByteCount);
  140. auto ptrBufferView = rhiBuffer->BuildBufferView(bufferViewDescriptor);
  141. shaderStreamBufferViews->m_streamViewsBySemantic.emplace(AZStd::move(shaderSemantic), ptrBufferView);
  142. }
  143. return shaderStreamBufferViews;
  144. }
  145. const MeshFeatureProcessorInterface::MeshHandle& ShaderStreamBufferViewsBuilder::GetMeshHandle() const
  146. {
  147. return *m_meshHandle;
  148. }
  149. // StreamBufferViewsBuilderInterface overrides End...
  150. ////////////////////////////////////////////////////////////
  151. void ShaderStreamBufferViewsBuilder::FinalizeShaderInputContract()
  152. {
  153. AZ_Assert(!m_shaderInputContract, "ShaderInputContract was already finalized.");
  154. m_shaderInputContract = AZStd::make_unique<AZ::RPI::ShaderInputContract>();
  155. for (const auto& streamInfo : m_streamsList)
  156. {
  157. AZ::RPI::ShaderInputContract::StreamChannelInfo streamChannelInfo;
  158. streamChannelInfo.m_semantic = AZ::RHI::ShaderSemantic::Parse(streamInfo.m_semanticName);
  159. streamChannelInfo.m_componentCount = AZ::RHI::GetFormatComponentCount(streamInfo.m_streamFormat);
  160. streamChannelInfo.m_isOptional = streamInfo.m_isOptional;
  161. m_shaderInputContract->m_streamChannels.emplace_back(streamChannelInfo);
  162. }
  163. }
  164. AZ::RHI::Ptr<AZ::RHI::BufferView> ShaderStreamBufferViewsBuilder::BuildShaderIndexBufferView(
  165. const AZ::RPI::ModelLod::Mesh& modelLodMesh) const
  166. {
  167. AZ_Assert(modelLodMesh.GetDrawArguments().m_type == AZ::RHI::DrawType::Indexed, "We only support indexed geometry!");
  168. const AZ::RHI::IndexBufferView& indexBufferView = modelLodMesh.GetIndexBufferView();
  169. uint32_t indexElementSize = indexBufferView.GetIndexFormat() == AZ::RHI::IndexFormat::Uint16 ? 2 : 4;
  170. uint32_t indexElementCount = (uint32_t)indexBufferView.GetBuffer()->GetDescriptor().m_byteCount / indexElementSize;
  171. AZ::RHI::BufferViewDescriptor indexBufferDescriptor;
  172. indexBufferDescriptor.m_elementOffset = 0;
  173. indexBufferDescriptor.m_elementCount = indexElementCount;
  174. indexBufferDescriptor.m_elementSize = indexElementSize;
  175. indexBufferDescriptor.m_elementFormat =
  176. indexBufferView.GetIndexFormat() == AZ::RHI::IndexFormat::Uint16 ? AZ::RHI::Format::R16_UINT : AZ::RHI::Format::R32_UINT;
  177. auto* rhiBuffer = const_cast<AZ::RHI::Buffer*>(indexBufferView.GetBuffer());
  178. return rhiBuffer->BuildBufferView(indexBufferDescriptor);
  179. }
  180. } // namespace Render
  181. } // namespace AZ