Vertex.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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. #pragma once
  9. #include <AzCore/std/containers/vector.h>
  10. #include <AzCore/std/string/string.h>
  11. #include <AzCore/std/containers/array.h>
  12. #include <CryCommon/BaseTypes.h>
  13. #include <CryCommon/VertexFormats.h>
  14. namespace AZ
  15. {
  16. namespace Vertex
  17. {
  18. const uint32_t VERTEX_BUFFER_ALIGNMENT = 4;
  19. // This enum must only have 8 entries because only 3 bits are used to store usage.
  20. enum class AttributeUsage : uint8
  21. {
  22. Position,
  23. Color,
  24. Normal,
  25. TexCoord,
  26. Weights,
  27. Indices,
  28. Tangent,
  29. BiTangent,
  30. NumUsages
  31. };
  32. struct AttributeUsageData
  33. {
  34. AZStd::string friendlyName;
  35. AZStd::string semanticName;
  36. };
  37. static AttributeUsageData AttributeUsageDataTable[(uint)AttributeUsage::NumUsages] =
  38. {
  39. // {friendlyName, semanticName}
  40. { "Position", "POSITION" },
  41. { "Color", "COLOR" },
  42. { "Normal", "NORMAL" },
  43. { "TexCoord", "TEXCOORD" },
  44. { "Weights", "BLENDWEIGHT" },
  45. { "Indices", "BLENDINDICES" },
  46. { "Tangent", "TEXCOORD" },
  47. { "BiTangent", "TEXCOORD" }
  48. };
  49. // This enum must have 32 or less entries as 5 bits are used to store type.
  50. enum class AttributeType : uint8
  51. {
  52. Float16_1 = 0,
  53. Float16_2,
  54. Float16_4,
  55. Float32_1,
  56. Float32_2,
  57. Float32_3,
  58. Float32_4,
  59. Byte_1,
  60. Byte_2,
  61. Byte_4,
  62. Short_1,
  63. Short_2,
  64. Short_4,
  65. UInt16_1,
  66. UInt16_2,
  67. UInt16_4,
  68. UInt32_1,
  69. UInt32_2,
  70. UInt32_3,
  71. UInt32_4,
  72. NumTypes
  73. };
  74. struct AttributeTypeData
  75. {
  76. AZStd::string friendlyName;
  77. uint8 byteSize;
  78. };
  79. static AttributeTypeData AttributeTypeDataTable[(unsigned int)AZ::Vertex::AttributeType::NumTypes] =
  80. {
  81. { "Float16_1", 2 },
  82. { "Float16_2", 4 },
  83. { "Float16_4", 8 },
  84. { "Float32_1", 4 },
  85. { "Float32_2", 8 },
  86. { "Float32_3", 12 },
  87. { "Float32_4", 16 },
  88. { "Byte_1", 1 },
  89. { "Byte_2", 2 },
  90. { "Byte_4", 4 },
  91. { "Short_1", 2 },
  92. { "Short_2", 4 },
  93. { "Short_4", 8 },
  94. { "UInt16_1", 2 },
  95. { "UInt16_2", 4 },
  96. { "UInt16_4", 8 },
  97. { "UInt32_1", 4 },
  98. { "UInt32_2", 8 },
  99. { "UInt32_3", 12 },
  100. { "UInt32_4", 16 },
  101. };
  102. //! Stores the usage, type, and byte length of an individual vertex attribute
  103. class Attribute
  104. {
  105. public:
  106. // Usage stored in the 3 lower bits and Type stored in the 5 upper bits.
  107. static const uint8 kUsageBitCount = 3;
  108. static const uint8 kUsageMask = 0x07;
  109. static const uint8 kTypeMask = 0xf8;
  110. static uint8 CreateAttribute(AttributeUsage usage, AttributeType type)
  111. {
  112. return (static_cast<uint8>(type) << kUsageBitCount) | static_cast<uint8>(usage);
  113. }
  114. static AttributeUsage GetUsage(const uint8 attribute)
  115. {
  116. return static_cast<AttributeUsage>(attribute & kUsageMask);
  117. }
  118. static AttributeType GetType(const uint8 attribute)
  119. {
  120. return static_cast<AttributeType>((attribute & kTypeMask) >> kUsageBitCount);
  121. }
  122. static uint8 GetByteLength(const uint8 attribute)
  123. {
  124. return AttributeTypeDataTable[(uint)GetType(attribute)].byteSize;
  125. }
  126. static const AZStd::string& GetSemanticName(uint8 attribute)
  127. {
  128. return AttributeUsageDataTable[(uint)GetUsage(attribute)].semanticName;
  129. }
  130. };
  131. //! Flexible vertex format class
  132. class Format
  133. {
  134. public:
  135. Format(){};
  136. //! Conversion from old hard-coded EVertexFormat enum to new, flexible vertex class
  137. Format(EVertexFormat format)
  138. {
  139. m_enum = eVF_Unknown;
  140. m_numAttributes = 0;
  141. switch (format)
  142. {
  143. case eVF_Unknown:
  144. m_enum = eVF_Unknown;
  145. break;
  146. case eVF_P3F_C4B_T2F:
  147. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3));
  148. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4));
  149. AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2));
  150. m_enum = eVF_P3F_C4B_T2F;
  151. break;
  152. case eVF_P3S_C4B_T2S:
  153. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_4));// vec3f16 is backed by a CryHalf4
  154. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4));
  155. AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2));
  156. m_enum = eVF_P3S_C4B_T2S;
  157. break;
  158. // Additional streams
  159. case eVF_W4B_I4S:// Skinned weights/indices stream.
  160. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Weights, AttributeType::Byte_4));
  161. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Indices, AttributeType::UInt16_4));
  162. m_enum = eVF_W4B_I4S;
  163. break;
  164. case eVF_P3F:// Velocity stream.
  165. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3));
  166. m_enum = eVF_P3F;
  167. break;
  168. case eVF_P2F_C4B_T2F_F4B:
  169. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_2));
  170. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4));
  171. AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2));
  172. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Indices, AttributeType::UInt16_2));
  173. m_enum = eVF_P2F_C4B_T2F_F4B;
  174. break;
  175. case eVF_P3F_C4B:
  176. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3));
  177. AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4));
  178. m_enum = eVF_P3F_C4B;
  179. break;
  180. case eVF_Max:
  181. default:
  182. AZ_Error("VF", false, "Invalid vertex format");
  183. m_enum = eVF_Unknown;
  184. }
  185. CalculateStrideAndUsageCounts();
  186. }
  187. //! Get the equivalent old-style EVertexFormat enum
  188. uint GetEnum() const { return m_enum; }
  189. static const uint8 kHas16BitFloatPosition = 0x4;
  190. static const uint8 kHas16BitFloatTexCoords = 0x2;
  191. static const uint8 kHas32BitFloatTexCoords = 0x1;
  192. uint32 GetAttributeUsageCount(AttributeUsage usage) const
  193. {
  194. return (uint32)m_attributeUsageCounts[(uint)usage];
  195. }
  196. const uint8* GetAttributes( uint32 &outCount) const
  197. {
  198. outCount = m_numAttributes;
  199. return m_vertexAttributes;
  200. }
  201. uint GetStride(void) const { return m_stride; }
  202. // Quick comparison operators.
  203. bool operator==(const Format& other) const
  204. {
  205. return m_enum == other.m_enum;
  206. }
  207. bool operator!=(const Format& other) const
  208. {
  209. return !(*this == other);
  210. }
  211. bool operator==(const EVertexFormat& other) const
  212. {
  213. return m_enum == other;
  214. }
  215. // Used in RendermeshMerger.cpp
  216. // CHWShader_D3D::mfUpdateFXVertexFormat and CHWShader_D3D::mfVertexFormat want the max between two vertex formats...why? It seems like a bad guess of which vertex format to use since there's no particular order to EVertexFormats...other than the more specialized EVertexFormats come after the base EVertexFormats
  217. bool operator<(const Format& other) const
  218. {
  219. return m_enum < other.m_enum;
  220. }
  221. bool operator<=(const Format& other) const
  222. {
  223. return (*this == other || *this < other);
  224. }
  225. bool operator>(const Format& other) const
  226. {
  227. return !(*this <= other);
  228. }
  229. bool operator>=(const Format& other) const
  230. {
  231. return (*this == other || *this > other);
  232. }
  233. private:
  234. void AddAttribute(uint8 attribute)
  235. {
  236. AZ_Assert(m_numAttributes < kMaxAttributes, "Too many attributes added. Change the size of kMaxAttributes");
  237. m_vertexAttributes[m_numAttributes++] = attribute;
  238. // Update the flags.
  239. AttributeUsage usage = Attribute::GetUsage(attribute);
  240. AttributeType type = Attribute::GetType(attribute);
  241. if (usage == AttributeUsage::TexCoord)
  242. {
  243. if (type == AttributeType::Float16_2) {
  244. m_flags |= kHas16BitFloatTexCoords;
  245. }
  246. else if (type == AttributeType::Float32_2 || type == AttributeType::Float32_3 || type == AttributeType::Float32_4) {
  247. m_flags |= kHas32BitFloatTexCoords;
  248. }
  249. }
  250. else if (usage == AttributeUsage::Position && type == AttributeType::Float16_4) {
  251. m_flags |= kHas16BitFloatPosition;
  252. }
  253. }
  254. //! Calculates the sum of the size in bytes of all attributes that make up this format
  255. void CalculateStrideAndUsageCounts()
  256. {
  257. static_assert((uint32)AttributeUsage::NumUsages <= 8, "We use 3 bits to represent usage so we only support 8 usages for a vertex format attribute.");
  258. static_assert((uint32)AttributeType::NumTypes <= 32, "We use 5 bits to represent type so we only support up to 32 types for a vertex format attribute.");
  259. for (uint index = 0; index < (uint)AttributeUsage::NumUsages; ++index)
  260. {
  261. m_attributeUsageCounts[index] = 0;
  262. }
  263. uint32 stride = 0;
  264. for (uint ii = 0; ii < m_numAttributes; ++ii)
  265. {
  266. uint8 attribute = m_vertexAttributes[ii];
  267. stride += Attribute::GetByteLength(attribute);
  268. m_attributeUsageCounts[(uint)Attribute::GetUsage(attribute)]++;
  269. }
  270. AZ_Assert(stride < (0x1 << (sizeof(m_stride) * 8)), "Vertex stride is larger than the maximum supported, update the type for m_stride in Vertex.h");
  271. m_stride = static_cast<uint8>(stride);
  272. }
  273. #ifdef PARTICLE_MOTION_BLUR
  274. static const uint32_t kMaxAttributes = 8;
  275. #else
  276. static const uint32_t kMaxAttributes = 10;
  277. #endif
  278. uint8 m_vertexAttributes[kMaxAttributes] = { 0 };
  279. uint8 m_attributeUsageCounts[(uint)AttributeUsage::NumUsages] = { 0 };
  280. uint8 m_numAttributes = 0;
  281. uint8 m_enum = eVF_Unknown;
  282. uint8 m_stride = 0;
  283. uint8 m_flags = 0x0;
  284. };
  285. }
  286. }