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#include "RenderAPI/BsVertexDataDesc.h"
4#include "Managers/BsHardwareBufferManager.h"
5#include "Private/RTTI/BsVertexDataDescRTTI.h"
6
7namespace bs
8{
9 void VertexDataDesc::addVertElem(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx,
10 UINT32 streamIdx, UINT32 instanceStepRate)
11 {
12 clearIfItExists(type, semantic, semanticIdx, streamIdx);
13
14 VertexElement newElement(streamIdx, 0, type, semantic, semanticIdx, instanceStepRate);
15
16 // Insert it so it is sorted by stream
17 UINT32 insertToIndex = (UINT32)mVertexElements.size();
18 UINT32 idx = 0;
19 for(auto& elem : mVertexElements)
20 {
21 if(elem.getStreamIdx() > streamIdx)
22 {
23 insertToIndex = idx;
24 break;
25 }
26
27 idx++;
28 }
29
30 mVertexElements.insert(mVertexElements.begin() + insertToIndex, newElement);
31 }
32
33 Vector<VertexElement> VertexDataDesc::createElements() const
34 {
35 UINT32 maxStreamIdx = getMaxStreamIdx();
36
37 UINT32 numStreams = maxStreamIdx + 1;
38 UINT32* streamOffsets = bs_newN<UINT32>(numStreams);
39 for (UINT32 i = 0; i < numStreams; i++)
40 streamOffsets[i] = 0;
41
42 Vector<VertexElement> declarationElements;
43 for (auto& vertElem : mVertexElements)
44 {
45 UINT32 streamIdx = vertElem.getStreamIdx();
46
47 declarationElements.push_back(VertexElement(streamIdx, streamOffsets[streamIdx], vertElem.getType(),
48 vertElem.getSemantic(), vertElem.getSemanticIdx(), vertElem.getInstanceStepRate()));
49
50 streamOffsets[streamIdx] += vertElem.getSize();
51 }
52
53 bs_deleteN(streamOffsets, numStreams);
54
55 return declarationElements;
56 }
57
58 UINT32 VertexDataDesc::getMaxStreamIdx() const
59 {
60 UINT32 maxStreamIdx = 0;
61 UINT32 numElems = (UINT32)mVertexElements.size();
62 for(UINT32 i = 0; i < numElems; i++)
63 {
64 for(auto& vertElem : mVertexElements)
65 {
66 maxStreamIdx = std::max((UINT32)maxStreamIdx, (UINT32)vertElem.getStreamIdx());
67 }
68 }
69
70 return maxStreamIdx;
71 }
72
73 bool VertexDataDesc::hasStream(UINT32 streamIdx) const
74 {
75 for(auto& vertElem : mVertexElements)
76 {
77 if(vertElem.getStreamIdx() == streamIdx)
78 return true;
79 }
80
81 return false;
82 }
83
84 bool VertexDataDesc::hasElement(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
85 {
86 auto findIter = std::find_if(mVertexElements.begin(), mVertexElements.end(),
87 [semantic, semanticIdx, streamIdx] (const VertexElement& x)
88 {
89 return x.getSemantic() == semantic && x.getSemanticIdx() == semanticIdx && x.getStreamIdx() == streamIdx;
90 });
91
92 if(findIter != mVertexElements.end())
93 {
94 return true;
95 }
96
97 return false;
98 }
99
100 UINT32 VertexDataDesc::getElementSize(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
101 {
102 for(auto& element : mVertexElements)
103 {
104 if(element.getSemantic() == semantic && element.getSemanticIdx() == semanticIdx && element.getStreamIdx() == streamIdx)
105 return element.getSize();
106 }
107
108 return -1;
109 }
110
111 UINT32 VertexDataDesc::getElementOffsetFromStream(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
112 {
113 UINT32 vertexOffset = 0;
114 for(auto& element : mVertexElements)
115 {
116 if(element.getStreamIdx() != streamIdx)
117 continue;
118
119 if(element.getSemantic() == semantic && element.getSemanticIdx() == semanticIdx)
120 break;
121
122 vertexOffset += element.getSize();
123 }
124
125 return vertexOffset;
126 }
127
128 UINT32 VertexDataDesc::getVertexStride(UINT32 streamIdx) const
129 {
130 UINT32 vertexStride = 0;
131 for(auto& element : mVertexElements)
132 {
133 if(element.getStreamIdx() == streamIdx)
134 vertexStride += element.getSize();
135 }
136
137 return vertexStride;
138 }
139
140 UINT32 VertexDataDesc::getVertexStride() const
141 {
142 UINT32 vertexStride = 0;
143 for(auto& element : mVertexElements)
144 {
145 vertexStride += element.getSize();
146 }
147
148 return vertexStride;
149 }
150
151 UINT32 VertexDataDesc::getStreamOffset(UINT32 streamIdx) const
152 {
153 UINT32 streamOffset = 0;
154 for(auto& element : mVertexElements)
155 {
156 if(element.getStreamIdx() == streamIdx)
157 break;
158
159 streamOffset += element.getSize();
160 }
161
162 return streamOffset;
163 }
164
165 const VertexElement* VertexDataDesc::getElement(VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx) const
166 {
167 auto findIter = std::find_if(mVertexElements.begin(), mVertexElements.end(),
168 [semantic, semanticIdx, streamIdx](const VertexElement& x)
169 {
170 return x.getSemantic() == semantic && x.getSemanticIdx() == semanticIdx && x.getStreamIdx() == streamIdx;
171 });
172
173 if (findIter != mVertexElements.end())
174 return &(*findIter);
175
176 return nullptr;
177 }
178
179 void VertexDataDesc::clearIfItExists(VertexElementType type, VertexElementSemantic semantic, UINT32 semanticIdx, UINT32 streamIdx)
180 {
181 auto findIter = std::find_if(mVertexElements.begin(), mVertexElements.end(),
182 [semantic, semanticIdx, streamIdx] (const VertexElement& x)
183 {
184 return x.getSemantic() == semantic && x.getSemanticIdx() == semanticIdx && x.getStreamIdx() == streamIdx;
185 });
186
187 if(findIter != mVertexElements.end())
188 {
189 mVertexElements.erase(findIter);
190 }
191 }
192
193 SPtr<VertexDataDesc> VertexDataDesc::create()
194 {
195 return bs_shared_ptr_new<VertexDataDesc>();
196 }
197
198 /************************************************************************/
199 /* SERIALIZATION */
200 /************************************************************************/
201
202 RTTITypeBase* VertexDataDesc::getRTTIStatic()
203 {
204 return VertexDataDescRTTI::instance();
205 }
206
207 RTTITypeBase* VertexDataDesc::getRTTI() const
208 {
209 return VertexDataDesc::getRTTIStatic();
210 }
211}