1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "RenderAPI/BsHardwareBuffer.h"
7#include "CoreThread/BsCoreObject.h"
8
9namespace bs
10{
11 /** @addtogroup RenderAPI
12 * @{
13 */
14
15 /** Descriptor structure used for initialization of a VertexBuffer. */
16 struct VERTEX_BUFFER_DESC
17 {
18 UINT32 vertexSize; /**< Size of a single vertex in the buffer, in bytes. */
19 UINT32 numVerts; /**< Number of vertices the buffer can hold. */
20 GpuBufferUsage usage = GBU_STATIC; /**< Usage that tells the hardware how will be buffer be used. */
21 bool streamOut = false; /**< If true the buffer will be usable for streaming out data from the GPU. */
22 };
23
24 /** Contains information about a vertex buffer buffer. */
25 class BS_CORE_EXPORT VertexBufferProperties
26 {
27 public:
28 VertexBufferProperties(UINT32 numVertices, UINT32 vertexSize);
29
30 /** Gets the size in bytes of a single vertex in this buffer. */
31 UINT32 getVertexSize() const { return mVertexSize; }
32
33 /** Get the number of vertices in this buffer. */
34 UINT32 getNumVertices() const { return mNumVertices; }
35
36 protected:
37 friend class VertexBuffer;
38 friend class ct::VertexBuffer;
39
40 UINT32 mNumVertices;
41 UINT32 mVertexSize;
42 };
43
44 /** Specialization of a hardware buffer used for holding vertex data. */
45 class BS_CORE_EXPORT VertexBuffer : public CoreObject
46 {
47 public:
48 virtual ~VertexBuffer() = default;
49
50 /**
51 * Retrieves a core implementation of a vertex buffer usable only from the core thread.
52 *
53 * @note Core thread only.
54 */
55 SPtr<ct::VertexBuffer> getCore() const;
56
57 /** @copydoc HardwareBufferManager::createVertexBuffer */
58 static SPtr<VertexBuffer> create(const VERTEX_BUFFER_DESC& desc);
59
60 static const int MAX_SEMANTIC_IDX = 8;
61 protected:
62 friend class HardwareBufferManager;
63
64 VertexBuffer(const VERTEX_BUFFER_DESC& desc);
65
66 /** @copydoc CoreObject::createCore */
67 SPtr<ct::CoreObject> createCore() const override;
68
69 VertexBufferProperties mProperties;
70 GpuBufferUsage mUsage;
71 bool mStreamOut;
72 };
73
74 /** @} */
75
76 namespace ct
77 {
78 /** @addtogroup RenderAPI-Internal
79 * @{
80 */
81
82 /** Core thread specific implementation of a bs::VertexBuffer. */
83 class BS_CORE_EXPORT VertexBuffer : public CoreObject, public HardwareBuffer
84 {
85 public:
86 VertexBuffer(const VERTEX_BUFFER_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT);
87 virtual ~VertexBuffer();
88
89 /** Returns information about the vertex buffer. */
90 const VertexBufferProperties& getProperties() const { return mProperties; }
91
92 /** @copydoc HardwareBuffer::readData */
93 void readData(UINT32 offset, UINT32 length, void* dest, UINT32 deviceIdx = 0, UINT32 queueIdx = 0) override;
94
95 /** @copydoc HardwareBuffer::writeData */
96 void writeData(UINT32 offset, UINT32 length, const void* source,
97 BufferWriteType writeFlags = BWT_NORMAL, UINT32 queueIdx = 0) override;
98
99 /** @copydoc HardwareBuffer::copyData */
100 void copyData(HardwareBuffer& srcBuffer, UINT32 srcOffset, UINT32 dstOffset, UINT32 length,
101 bool discardWholeBuffer = false, const SPtr<CommandBuffer>& commandBuffer = nullptr) override;
102
103 /**
104 * Returns a view of this buffer that can be used for load-store operations. Buffer must have been created with
105 * the GBU_LOADSTORE usage flag.
106 *
107 * @param[in] type Type of buffer to view the contents as. Only supported values are GBT_STANDARD and
108 * GBT_STRUCTURED.
109 * @param[in] format Format of the data in the buffer. Size of the underlying buffer must be divisible by
110 * the size of an individual element of this format. Must be BF_UNKNOWN if buffer type
111 * is GBT_STRUCTURED.
112 * @param[in] elementSize Size of the individual element in the buffer. Size of the underlying buffer must be
113 * divisible by this size. Must be 0 if buffer type is GBT_STANDARD (element size gets
114 * deduced from format).
115 * @return Buffer usable for load store operations or null if the operation fails. Failure
116 * can happen if the buffer hasn't been created with GBU_LOADSTORE usage or if the
117 * element size doesn't divide the current buffer size.
118 */
119 SPtr<GpuBuffer> getLoadStore(GpuBufferType type, GpuBufferFormat format, UINT32 elementSize = 0);
120
121 /** @copydoc HardwareBufferManager::createVertexBuffer */
122 static SPtr<VertexBuffer> create(const VERTEX_BUFFER_DESC& desc, GpuDeviceFlags deviceMask = GDF_DEFAULT);
123
124 protected:
125 friend class HardwareBufferManager;
126
127 /** @copydoc HardwareBuffer::map */
128 void* map(UINT32 offset, UINT32 length, GpuLockOptions options, UINT32 deviceIdx, UINT32 queueIdx) override;
129
130 /** @copydoc HardwareBuffer::unmap */
131 void unmap() override;
132
133 /** @copydoc CoreObject::initialize */
134 void initialize() override;
135
136 VertexBufferProperties mProperties;
137
138 HardwareBuffer* mBuffer = nullptr;
139 SPtr<HardwareBuffer> mSharedBuffer;
140 Vector<SPtr<GpuBuffer>> mLoadStoreViews;
141
142 typedef void(*Deleter)(HardwareBuffer*);
143 Deleter mBufferDeleter = nullptr;
144 };
145
146 /** @} */
147 }
148}