242 lines
7.7 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. //
  11. // The VertexBuffer and VertexDeclaration classes
  12. // ----------------------------------------------
  13. //
  14. #if !defined __LOL_GPU_VERTEXBUFFER_H__
  15. #define __LOL_GPU_VERTEXBUFFER_H__
  16. #include <cstring>
  17. namespace lol
  18. {
  19. class VertexBuffer
  20. {
  21. friend class VertexDeclaration;
  22. public:
  23. VertexBuffer(size_t size);
  24. ~VertexBuffer();
  25. size_t GetSize();
  26. void *Lock(size_t offset, size_t size);
  27. void Unlock();
  28. private:
  29. class VertexBufferData *m_data;
  30. };
  31. /* A safe enum to indicate what kind of primitive to draw. Used in
  32. * VertexDeclaration::DrawElements() for instance. */
  33. LOL_SAFE_ENUM(MeshPrimitive,
  34. Triangles,
  35. TriangleStrips,
  36. TriangleFans,
  37. Points,
  38. Lines,
  39. );
  40. class VertexStreamBase
  41. {
  42. friend class VertexDeclaration;
  43. public:
  44. enum
  45. {
  46. Typevoid = 0,
  47. #if LOL_FEATURE_CXX11_UNRESTRICTED_UNIONS
  48. Typehalf, Typef16vec2, Typef16vec3, Typef16vec4,
  49. #endif
  50. Typefloat, Typevec2, Typevec3, Typevec4,
  51. Typedouble, Typedvec2, Typedvec3, Typedvec4,
  52. Typeint8_t, Typei8vec2, Typei8vec3, Typei8vec4,
  53. Typeuint8_t, Typeu8vec2, Typeu8vec3, Typeu8vec4,
  54. Typeint16_t, Typei16vec2, Typei16vec3, Typei16vec4,
  55. Typeuint16_t, Typeu16vec2, Typeu16vec3, Typeu16vec4,
  56. Typeint32_t, Typeivec2, Typeivec3, Typeivec4,
  57. Typeuint32_t, Typeuvec2, Typeuvec3, Typeuvec4,
  58. };
  59. int GetSize() const
  60. {
  61. int size = 0, i = 0;
  62. while (m_streams[i].size)
  63. size += m_streams[i++].size;
  64. return size;
  65. }
  66. int GetStreamCount() const
  67. {
  68. int i = 0;
  69. while (m_streams[i].size) ++i;
  70. return i;
  71. }
  72. VertexUsage GetUsage(int index) const
  73. {
  74. return m_streams[index].usage;
  75. }
  76. uint8_t GetType(int index) const
  77. {
  78. return m_streams[index].stream_type;
  79. }
  80. uint8_t GetSize(int index) const
  81. {
  82. return m_streams[index].size;
  83. }
  84. protected:
  85. #define __T(T) \
  86. static uint8_t GetType(T *x) { UNUSED(x); return Type##T; }
  87. __T(void)
  88. #if LOL_FEATURE_CXX11_UNRESTRICTED_UNIONS
  89. __T(half) __T(f16vec2) __T(f16vec3) __T(f16vec4)
  90. #endif
  91. __T(float) __T(vec2) __T(vec3) __T(vec4)
  92. __T(double) __T(dvec2) __T(dvec3) __T(dvec4)
  93. __T(int8_t) __T(i8vec2) __T(i8vec3) __T(i8vec4)
  94. __T(uint8_t) __T(u8vec2) __T(u8vec3) __T(u8vec4)
  95. __T(int16_t) __T(i16vec2) __T(i16vec3) __T(i16vec4)
  96. __T(uint16_t) __T(u16vec2) __T(u16vec3) __T(u16vec4)
  97. __T(int32_t) __T(ivec2) __T(ivec3) __T(ivec4)
  98. __T(uint32_t) __T(uvec2) __T(uvec3) __T(uvec4)
  99. #undef __T
  100. template<typename T> inline void AddStream(int n, VertexUsage usage)
  101. {
  102. m_streams[n].stream_type = GetType((T *)nullptr);
  103. m_streams[n].usage = usage;
  104. m_streams[n].size = sizeof(T);
  105. }
  106. VertexStreamBase() {}
  107. private:
  108. struct { uint8_t stream_type, size; VertexUsage usage; } m_streams[12 + 1];
  109. static VertexStreamBase const Empty;
  110. };
  111. /* Specialise this template for "void" to act as a NOP */
  112. template<>
  113. inline void VertexStreamBase::AddStream<void>(int n, VertexUsage usage)
  114. {
  115. UNUSED(usage);
  116. m_streams[n].size = 0;
  117. }
  118. template<typename T1 = void, typename T2 = void, typename T3 = void,
  119. typename T4 = void, typename T5 = void, typename T6 = void,
  120. typename T7 = void, typename T8 = void, typename T9 = void,
  121. typename T10 = void, typename T11 = void, typename T12 = void>
  122. class VertexStream : public VertexStreamBase
  123. {
  124. public:
  125. inline VertexStream(VertexUsage u1,
  126. VertexUsage u2 = VertexUsage::Position,
  127. VertexUsage u3 = VertexUsage::Position,
  128. VertexUsage u4 = VertexUsage::Position,
  129. VertexUsage u5 = VertexUsage::Position,
  130. VertexUsage u6 = VertexUsage::Position,
  131. VertexUsage u7 = VertexUsage::Position,
  132. VertexUsage u8 = VertexUsage::Position,
  133. VertexUsage u9 = VertexUsage::Position,
  134. VertexUsage u10 = VertexUsage::Position,
  135. VertexUsage u11 = VertexUsage::Position,
  136. VertexUsage u12 = VertexUsage::Position)
  137. {
  138. AddStream<T1>(0, u1); AddStream<T2>(1, u2);
  139. AddStream<T3>(2, u3); AddStream<T4>(3, u4);
  140. AddStream<T5>(4, u5); AddStream<T6>(5, u6);
  141. AddStream<T7>(6, u7); AddStream<T8>(7, u8);
  142. AddStream<T9>(8, u9); AddStream<T10>(9, u10);
  143. AddStream<T11>(10, u11); AddStream<T12>(11, u12);
  144. }
  145. };
  146. class VertexDeclaration
  147. {
  148. public:
  149. VertexDeclaration(VertexStreamBase const &s1 = VertexStreamBase::Empty,
  150. VertexStreamBase const &s2 = VertexStreamBase::Empty,
  151. VertexStreamBase const &s3 = VertexStreamBase::Empty,
  152. VertexStreamBase const &s4 = VertexStreamBase::Empty,
  153. VertexStreamBase const &s5 = VertexStreamBase::Empty,
  154. VertexStreamBase const &s6 = VertexStreamBase::Empty,
  155. VertexStreamBase const &s7 = VertexStreamBase::Empty,
  156. VertexStreamBase const &s8 = VertexStreamBase::Empty,
  157. VertexStreamBase const &s9 = VertexStreamBase::Empty,
  158. VertexStreamBase const &s10 = VertexStreamBase::Empty,
  159. VertexStreamBase const &s11 = VertexStreamBase::Empty,
  160. VertexStreamBase const &s12 = VertexStreamBase::Empty);
  161. ~VertexDeclaration();
  162. void Bind();
  163. /* Draw elements. See MeshPrimitive for a list of all available
  164. * types. Both skip and count are numbers of vertices, not primitives. */
  165. void DrawElements(MeshPrimitive type, int skip, int count);
  166. /* Draw elements. See MeshPrimitive for a list of all available
  167. * types. Both skip and count are numbers of indices, not primitives. */
  168. void DrawIndexedElements(MeshPrimitive type, int vbase, int vskip,
  169. int vcount, int skip, int count);
  170. void Unbind();
  171. void SetStream(VertexBuffer *vb, ShaderAttrib attr1,
  172. ShaderAttrib attr2 = ShaderAttrib(),
  173. ShaderAttrib attr3 = ShaderAttrib(),
  174. ShaderAttrib attr4 = ShaderAttrib(),
  175. ShaderAttrib attr5 = ShaderAttrib(),
  176. ShaderAttrib attr6 = ShaderAttrib(),
  177. ShaderAttrib attr7 = ShaderAttrib(),
  178. ShaderAttrib attr8 = ShaderAttrib(),
  179. ShaderAttrib attr9 = ShaderAttrib(),
  180. ShaderAttrib attr10 = ShaderAttrib(),
  181. ShaderAttrib attr11 = ShaderAttrib(),
  182. ShaderAttrib attr12 = ShaderAttrib());
  183. void SetStream(VertexBuffer *vb, ShaderAttrib attribs[]);
  184. int GetStreamCount() const;
  185. VertexStreamBase GetStream(int index) const;
  186. private:
  187. void Initialize();
  188. void AddStream(VertexStreamBase const &);
  189. struct
  190. {
  191. uint8_t stream_type, index, size;
  192. VertexUsage usage;
  193. int reg;
  194. } m_streams[12 + 1];
  195. int m_count;
  196. private:
  197. class VertexDeclarationData *m_data;
  198. };
  199. } /* namespace lol */
  200. #endif // __LOL_GPU_VERTEXBUFFER_H__