InputStreamLayout.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 <Atom/RHI.Reflect/InputStreamLayout.h>
  9. #include <AzCore/Serialization/SerializeContext.h>
  10. #include <AzCore/Utils/TypeHash.h>
  11. namespace AZ::RHI
  12. {
  13. StreamChannelDescriptor::StreamChannelDescriptor(
  14. ShaderSemantic semantic,
  15. Format format,
  16. uint32_t byteOffset,
  17. uint32_t bufferIndex)
  18. : m_semantic{AZStd::move(semantic)}
  19. , m_format{format}
  20. , m_byteOffset{byteOffset}
  21. , m_bufferIndex{bufferIndex}
  22. {}
  23. HashValue64 StreamChannelDescriptor::GetHash(HashValue64 seed) const
  24. {
  25. seed = m_semantic.GetHash(seed);
  26. seed = TypeHash64(m_format, seed);
  27. seed = TypeHash64(m_byteOffset, seed);
  28. seed = TypeHash64(m_bufferIndex, seed);
  29. return seed;
  30. }
  31. void StreamChannelDescriptor::Reflect(AZ::ReflectContext* context)
  32. {
  33. if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
  34. {
  35. serializeContext->Class<StreamChannelDescriptor>()
  36. ->Version(1)
  37. ->Field("m_semantic", &StreamChannelDescriptor::m_semantic)
  38. ->Field("m_format", &StreamChannelDescriptor::m_format)
  39. ->Field("m_byteOffset", &StreamChannelDescriptor::m_byteOffset)
  40. ->Field("m_bufferIndex", &StreamChannelDescriptor::m_bufferIndex);
  41. }
  42. }
  43. StreamBufferDescriptor::StreamBufferDescriptor(
  44. StreamStepFunction stepFunction,
  45. uint32_t stepRate,
  46. uint32_t byteStride)
  47. : m_stepFunction{stepFunction}
  48. , m_stepRate{stepRate}
  49. , m_byteStride{byteStride}
  50. {}
  51. HashValue64 StreamBufferDescriptor::GetHash(HashValue64 seed) const
  52. {
  53. seed = TypeHash64(m_stepFunction, seed);
  54. seed = TypeHash64(m_stepRate, seed);
  55. seed = TypeHash64(m_byteStride, seed);
  56. return seed;
  57. }
  58. void StreamBufferDescriptor::Reflect(AZ::ReflectContext* context)
  59. {
  60. if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
  61. {
  62. serializeContext->Class<StreamBufferDescriptor>()
  63. ->Version(1)
  64. ->Field("m_stepFunction", &StreamBufferDescriptor::m_stepFunction)
  65. ->Field("m_stepRate", &StreamBufferDescriptor::m_stepRate)
  66. ->Field("m_byteStride", &StreamBufferDescriptor::m_byteStride);
  67. }
  68. }
  69. void InputStreamLayout::Reflect(AZ::ReflectContext* context)
  70. {
  71. if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
  72. {
  73. serializeContext->Class<InputStreamLayout>()
  74. ->Version(3)
  75. ->Field("m_topology", &InputStreamLayout::m_topology)
  76. ->Field("m_streamChannels", &InputStreamLayout::m_streamChannels)
  77. ->Field("m_streamBuffers", &InputStreamLayout::m_streamBuffers)
  78. ->Field("m_hash", &InputStreamLayout::m_hash);
  79. }
  80. }
  81. void InputStreamLayout::Clear()
  82. {
  83. m_topology = PrimitiveTopology::Undefined;
  84. m_streamChannels.clear();
  85. m_streamBuffers.clear();
  86. m_hash = HashValue64{ 0 };
  87. }
  88. bool InputStreamLayout::Finalize()
  89. {
  90. if (Validation::IsEnabled())
  91. {
  92. for (const auto& channelDescriptor : m_streamChannels)
  93. {
  94. if (channelDescriptor.m_bufferIndex >= m_streamBuffers.size())
  95. {
  96. AZ_Error("InputStreamLayout", false, "Channel %s[%d] references buffer index %d which does not exist.",
  97. channelDescriptor.m_semantic.m_name.GetCStr(), channelDescriptor.m_semantic.m_index, channelDescriptor.m_bufferIndex);
  98. return false;
  99. }
  100. }
  101. if (m_topology == PrimitiveTopology::Undefined)
  102. {
  103. AZ_Error("InputStreamLayout", false, "Topology is undefined.");
  104. return false;
  105. }
  106. }
  107. HashValue64 seed = TypeHash64(m_topology, HashValue64{ 0 });
  108. for (const StreamChannelDescriptor& channel : m_streamChannels)
  109. {
  110. seed = channel.GetHash(seed);
  111. }
  112. for (const StreamBufferDescriptor& buffer : m_streamBuffers)
  113. {
  114. seed = buffer.GetHash(seed);
  115. }
  116. m_hash = seed;
  117. return true;
  118. }
  119. bool InputStreamLayout::IsFinalized() const
  120. {
  121. return m_hash != HashValue64{ 0 };
  122. }
  123. void InputStreamLayout::SetTopology(PrimitiveTopology topology)
  124. {
  125. m_topology = topology;
  126. }
  127. void InputStreamLayout::AddStreamChannel(const StreamChannelDescriptor& descriptor)
  128. {
  129. m_streamChannels.push_back(descriptor);
  130. }
  131. void InputStreamLayout::AddStreamBuffer(const StreamBufferDescriptor& descriptor)
  132. {
  133. m_streamBuffers.push_back(descriptor);
  134. }
  135. const PrimitiveTopology InputStreamLayout::GetTopology() const
  136. {
  137. return m_topology;
  138. }
  139. AZStd::span<const StreamChannelDescriptor> InputStreamLayout::GetStreamChannels() const
  140. {
  141. return m_streamChannels;
  142. }
  143. AZStd::span<const StreamBufferDescriptor> InputStreamLayout::GetStreamBuffers() const
  144. {
  145. return m_streamBuffers;
  146. }
  147. HashValue64 InputStreamLayout::GetHash() const
  148. {
  149. return m_hash;
  150. }
  151. bool InputStreamLayout::operator == (const InputStreamLayout& rhs) const
  152. {
  153. bool same = (m_streamChannels.size() == rhs.m_streamChannels.size() && m_streamBuffers.size() == rhs.m_streamBuffers.size());
  154. if (same)
  155. {
  156. for (size_t index = 0; index < m_streamChannels.size(); index++)
  157. {
  158. if (m_streamChannels[index].GetHash() != rhs.m_streamChannels[index].GetHash())
  159. {
  160. same = false;
  161. break;
  162. }
  163. }
  164. if (same)
  165. {
  166. for (size_t index = 0; index < m_streamBuffers.size(); index++)
  167. {
  168. if (m_streamBuffers[index].GetHash() != rhs.m_streamBuffers[index].GetHash())
  169. {
  170. same = false;
  171. break;
  172. }
  173. }
  174. }
  175. }
  176. return same && m_hash == rhs.m_hash && m_topology == rhs.m_topology;
  177. }
  178. }