VertexBuffer.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Container/ArrayPtr.h"
  5. #include "../Core/Object.h"
  6. #include "../GraphicsAPI/GPUObject.h"
  7. #include "../GraphicsAPI/GraphicsDefs.h"
  8. namespace Urho3D
  9. {
  10. /// Hardware vertex buffer.
  11. class URHO3D_API VertexBuffer : public Object, public GPUObject
  12. {
  13. URHO3D_OBJECT(VertexBuffer, Object);
  14. public:
  15. /// Construct. Optionally force headless (no GPU-side buffer) operation.
  16. explicit VertexBuffer(Context* context, bool forceHeadless = false);
  17. /// Destruct.
  18. ~VertexBuffer() override;
  19. /// Mark the buffer destroyed on graphics context destruction. May be a no-op depending on the API.
  20. void OnDeviceLost() override;
  21. /// Recreate the buffer and restore data if applicable. May be a no-op depending on the API.
  22. void OnDeviceReset() override;
  23. /// Release buffer.
  24. void Release() override;
  25. /// Enable shadowing in CPU memory. Shadowing is forced on if the graphics subsystem does not exist.
  26. /// @property
  27. void SetShadowed(bool enable);
  28. /// Set size, vertex elements and dynamic mode. Previous data will be lost.
  29. bool SetSize(i32 vertexCount, const Vector<VertexElement>& elements, bool dynamic = false);
  30. /// Set size and vertex elements and dynamic mode using legacy element bitmask. Previous data will be lost.
  31. bool SetSize(i32 vertexCount, VertexElements elementMask, bool dynamic = false);
  32. /// Set all data in the buffer.
  33. bool SetData(const void* data);
  34. /// Set a data range in the buffer. Optionally discard data outside the range.
  35. bool SetDataRange(const void* data, i32 start, i32 count, bool discard = false);
  36. /// Lock the buffer for write-only editing. Return data pointer if successful. Optionally discard data outside the range.
  37. void* Lock(i32 start, i32 count, bool discard = false);
  38. /// Unlock the buffer and apply changes to the GPU buffer.
  39. void Unlock();
  40. /// Return whether CPU memory shadowing is enabled.
  41. /// @property
  42. bool IsShadowed() const { return shadowed_; }
  43. /// Return whether is dynamic.
  44. /// @property
  45. bool IsDynamic() const { return dynamic_; }
  46. /// Return whether is currently locked.
  47. bool IsLocked() const { return lockState_ != LOCK_NONE; }
  48. /// Return number of vertices.
  49. /// @property
  50. i32 GetVertexCount() const { return vertexCount_; }
  51. /// Return vertex size in bytes.
  52. /// @property
  53. i32 GetVertexSize() const { return vertexSize_; }
  54. /// Return vertex elements.
  55. /// @property
  56. const Vector<VertexElement>& GetElements() const { return elements_; }
  57. /// Return vertex element, or null if does not exist.
  58. const VertexElement* GetElement(VertexElementSemantic semantic, i8 index = 0) const;
  59. /// Return vertex element with specific type, or null if does not exist.
  60. const VertexElement* GetElement(VertexElementType type, VertexElementSemantic semantic, i8 index = 0) const;
  61. /// Return whether has a specified element semantic.
  62. bool HasElement(VertexElementSemantic semantic, i8 index = 0) const
  63. {
  64. assert(index >= 0);
  65. return GetElement(semantic, index) != nullptr;
  66. }
  67. /// Return whether has an element semantic with specific type.
  68. bool HasElement(VertexElementType type, VertexElementSemantic semantic, i8 index = 0) const
  69. {
  70. assert(index >= 0);
  71. return GetElement(type, semantic, index) != nullptr;
  72. }
  73. /// Return offset of a element within vertex, or NINDEX if does not exist.
  74. i32 GetElementOffset(VertexElementSemantic semantic, i8 index = 0) const
  75. {
  76. assert(index >= 0);
  77. const VertexElement* element = GetElement(semantic, index);
  78. return element ? element->offset_ : NINDEX;
  79. }
  80. /// Return offset of a element with specific type within vertex, or NINDEX if element does not exist.
  81. i32 GetElementOffset(VertexElementType type, VertexElementSemantic semantic, i8 index = 0) const
  82. {
  83. assert(index >= 0);
  84. const VertexElement* element = GetElement(type, semantic, index);
  85. return element ? element->offset_ : NINDEX;
  86. }
  87. /// Return legacy vertex element mask. Note that both semantic and type must match the legacy element for a mask bit to be set.
  88. /// @property
  89. VertexElements GetElementMask() const { return elementMask_; }
  90. /// Return CPU memory shadow data.
  91. byte* GetShadowData() const { return shadowData_.Get(); }
  92. /// Return shared array pointer to the CPU memory shadow data.
  93. SharedArrayPtr<byte> GetShadowDataShared() const { return shadowData_; }
  94. /// Return buffer hash for building vertex declarations. Used internally.
  95. hash64 GetBufferHash(i32 streamIndex) { return elementHash_ << (streamIndex * 16); }
  96. /// Return element with specified type and semantic from a vertex element list, or null if does not exist.
  97. static const VertexElement* GetElement(const Vector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, i8 index = 0);
  98. /// Return whether element list has a specified element type and semantic.
  99. static bool HasElement(const Vector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, i8 index = 0);
  100. /// Return element offset for specified type and semantic from a vertex element list, or NINDEX if does not exist.
  101. static i32 GetElementOffset(const Vector<VertexElement>& elements, VertexElementType type, VertexElementSemantic semantic, i8 index = 0);
  102. /// Return a vertex element list from a legacy element bitmask.
  103. static Vector<VertexElement> GetElements(VertexElements elementMask);
  104. /// Return vertex size from an element list.
  105. static i32 GetVertexSize(const Vector<VertexElement>& elements);
  106. /// Return vertex size for a legacy vertex element bitmask.
  107. static i32 GetVertexSize(VertexElements elementMask);
  108. /// Update offsets of vertex elements.
  109. static void UpdateOffsets(Vector<VertexElement>& elements);
  110. private:
  111. /// Update offsets of vertex elements.
  112. void UpdateOffsets();
  113. /// Create buffer.
  114. bool Create();
  115. /// Update the shadow data to the GPU buffer.
  116. bool UpdateToGPU();
  117. /// Map the GPU buffer into CPU memory. Not used on OpenGL.
  118. void* MapBuffer(i32 start, i32 count, bool discard);
  119. /// Unmap the GPU buffer. Not used on OpenGL.
  120. void UnmapBuffer();
  121. #ifdef URHO3D_OPENGL
  122. void OnDeviceLost_OGL();
  123. void OnDeviceReset_OGL();
  124. void Release_OGL();
  125. bool SetData_OGL(const void* data);
  126. bool SetDataRange_OGL(const void* data, i32 start, i32 count, bool discard = false);
  127. void* Lock_OGL(i32 start, i32 count, bool discard);
  128. void Unlock_OGL();
  129. bool Create_OGL();
  130. bool UpdateToGPU_OGL();
  131. void* MapBuffer_OGL(i32 start, i32 count, bool discard);
  132. void UnmapBuffer_OGL();
  133. #endif // def URHO3D_OPENGL
  134. #ifdef URHO3D_D3D11
  135. void OnDeviceLost_D3D11();
  136. void OnDeviceReset_D3D11();
  137. void Release_D3D11();
  138. bool SetData_D3D11(const void* data);
  139. bool SetDataRange_D3D11(const void* data, i32 start, i32 count, bool discard = false);
  140. void* Lock_D3D11(i32 start, i32 count, bool discard);
  141. void Unlock_D3D11();
  142. bool Create_D3D11();
  143. bool UpdateToGPU_D3D11();
  144. void* MapBuffer_D3D11(i32 start, i32 count, bool discard);
  145. void UnmapBuffer_D3D11();
  146. #endif // def URHO3D_D3D11
  147. /// Shadow data.
  148. SharedArrayPtr<byte> shadowData_;
  149. /// Number of vertices.
  150. i32 vertexCount_{};
  151. /// Vertex size.
  152. i32 vertexSize_{};
  153. /// Vertex elements.
  154. Vector<VertexElement> elements_;
  155. /// Vertex element hash.
  156. hash64 elementHash_{};
  157. /// Vertex element legacy bitmask.
  158. VertexElements elementMask_{};
  159. /// Buffer locking state.
  160. LockState lockState_{LOCK_NONE};
  161. /// Lock start vertex.
  162. i32 lockStart_{};
  163. /// Lock number of vertices.
  164. i32 lockCount_{};
  165. /// Scratch buffer for fallback locking.
  166. void* lockScratchData_{};
  167. /// Dynamic flag.
  168. bool dynamic_{};
  169. /// Shadowed flag.
  170. bool shadowed_{};
  171. /// Discard lock flag. Used by OpenGL only.
  172. bool discardLock_{};
  173. };
  174. }