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/BsVertexDeclaration.h" |
4 | #include "Private/RTTI/BsVertexDeclarationRTTI.h" |
5 | #include "Managers/BsHardwareBufferManager.h" |
6 | #include "RenderAPI/BsRenderAPI.h" |
7 | |
8 | namespace bs |
9 | { |
10 | VertexElement::VertexElement(UINT16 source, UINT32 offset, |
11 | VertexElementType theType, VertexElementSemantic semantic, UINT16 index, UINT32 instanceStepRate) |
12 | : mSource(source), mOffset(offset), mType(theType), mSemantic(semantic), mIndex(index) |
13 | , mInstanceStepRate(instanceStepRate) |
14 | { |
15 | } |
16 | |
17 | UINT32 VertexElement::getSize(void) const |
18 | { |
19 | return getTypeSize(mType); |
20 | } |
21 | |
22 | UINT32 VertexElement::getTypeSize(VertexElementType etype) |
23 | { |
24 | switch(etype) |
25 | { |
26 | case VET_COLOR: |
27 | case VET_COLOR_ABGR: |
28 | case VET_COLOR_ARGB: |
29 | return sizeof(RGBA); |
30 | case VET_UBYTE4_NORM: |
31 | return sizeof(UINT32); |
32 | case VET_FLOAT1: |
33 | return sizeof(float); |
34 | case VET_FLOAT2: |
35 | return sizeof(float) * 2; |
36 | case VET_FLOAT3: |
37 | return sizeof(float) * 3; |
38 | case VET_FLOAT4: |
39 | return sizeof(float) * 4; |
40 | case VET_USHORT1: |
41 | return sizeof(UINT16); |
42 | case VET_USHORT2: |
43 | return sizeof(UINT16) * 2; |
44 | case VET_USHORT4: |
45 | return sizeof(UINT16) * 4; |
46 | case VET_SHORT1: |
47 | return sizeof(INT16); |
48 | case VET_SHORT2: |
49 | return sizeof(INT16) * 2; |
50 | case VET_SHORT4: |
51 | return sizeof(INT16) * 4; |
52 | case VET_UINT1: |
53 | return sizeof(UINT32); |
54 | case VET_UINT2: |
55 | return sizeof(UINT32) * 2; |
56 | case VET_UINT3: |
57 | return sizeof(UINT32) * 3; |
58 | case VET_UINT4: |
59 | return sizeof(UINT32) * 4; |
60 | case VET_INT4: |
61 | return sizeof(INT32) * 4; |
62 | case VET_INT1: |
63 | return sizeof(INT32); |
64 | case VET_INT2: |
65 | return sizeof(INT32) * 2; |
66 | case VET_INT3: |
67 | return sizeof(INT32) * 3; |
68 | case VET_UBYTE4: |
69 | return sizeof(UINT8) * 4; |
70 | default: |
71 | break; |
72 | } |
73 | |
74 | return 0; |
75 | } |
76 | |
77 | unsigned short VertexElement::getTypeCount(VertexElementType etype) |
78 | { |
79 | switch (etype) |
80 | { |
81 | case VET_COLOR: |
82 | case VET_COLOR_ABGR: |
83 | case VET_COLOR_ARGB: |
84 | return 4; |
85 | case VET_FLOAT1: |
86 | case VET_SHORT1: |
87 | case VET_USHORT1: |
88 | case VET_INT1: |
89 | case VET_UINT1: |
90 | return 1; |
91 | case VET_FLOAT2: |
92 | case VET_SHORT2: |
93 | case VET_USHORT2: |
94 | case VET_INT2: |
95 | case VET_UINT2: |
96 | return 2; |
97 | case VET_FLOAT3: |
98 | case VET_INT3: |
99 | case VET_UINT3: |
100 | return 3; |
101 | case VET_FLOAT4: |
102 | case VET_SHORT4: |
103 | case VET_USHORT4: |
104 | case VET_INT4: |
105 | case VET_UINT4: |
106 | case VET_UBYTE4: |
107 | case VET_UBYTE4_NORM: |
108 | return 4; |
109 | default: |
110 | break; |
111 | } |
112 | |
113 | BS_EXCEPT(InvalidParametersException, "Invalid type" ); |
114 | return 0; |
115 | } |
116 | |
117 | VertexElementType VertexElement::getBestColorVertexElementType() |
118 | { |
119 | // Use the current render system to determine if possible |
120 | if (ct::RenderAPI::instancePtr() != nullptr) |
121 | { |
122 | return ct::RenderAPI::instance().getCapabilities(0).vertexColorType; |
123 | } |
124 | else |
125 | { |
126 | // We can't know the specific type right now, so pick a type based on platform |
127 | #if BS_PLATFORM == BS_PLATFORM_WIN32 |
128 | return VET_COLOR_ARGB; // prefer D3D format on Windows |
129 | #else |
130 | return VET_COLOR_ABGR; // prefer GL format on everything else |
131 | #endif |
132 | |
133 | } |
134 | } |
135 | |
136 | bool VertexElement::operator== (const VertexElement& rhs) const |
137 | { |
138 | if (mType != rhs.mType || mIndex != rhs.mIndex || mOffset != rhs.mOffset || |
139 | mSemantic != rhs.mSemantic || mSource != rhs.mSource || mInstanceStepRate != rhs.mInstanceStepRate) |
140 | { |
141 | return false; |
142 | } |
143 | else |
144 | return true; |
145 | } |
146 | |
147 | bool VertexElement::operator!= (const VertexElement& rhs) const |
148 | { |
149 | return !(*this == rhs); |
150 | } |
151 | |
152 | size_t VertexElement::getHash(const VertexElement& element) |
153 | { |
154 | size_t hash = 0; |
155 | bs_hash_combine(hash, element.mType); |
156 | bs_hash_combine(hash, element.mIndex); |
157 | bs_hash_combine(hash, element.mOffset); |
158 | bs_hash_combine(hash, element.mSemantic); |
159 | bs_hash_combine(hash, element.mSource); |
160 | bs_hash_combine(hash, element.mInstanceStepRate); |
161 | |
162 | return hash; |
163 | } |
164 | |
165 | VertexDeclarationProperties::VertexDeclarationProperties(const Vector<VertexElement>& elements) |
166 | { |
167 | for (auto& elem : elements) |
168 | { |
169 | VertexElementType type = elem.getType(); |
170 | |
171 | if (elem.getType() == VET_COLOR) |
172 | type = VertexElement::getBestColorVertexElementType(); |
173 | |
174 | mElementList.push_back(VertexElement(elem.getStreamIdx(), elem.getOffset(), type, elem.getSemantic(), |
175 | elem.getSemanticIdx(), elem.getInstanceStepRate())); |
176 | } |
177 | } |
178 | |
179 | bool VertexDeclarationProperties::operator== (const VertexDeclarationProperties& rhs) const |
180 | { |
181 | if (mElementList.size() != rhs.mElementList.size()) |
182 | return false; |
183 | |
184 | auto myIter = mElementList.begin(); |
185 | auto theirIter = rhs.mElementList.begin(); |
186 | |
187 | for (; myIter != mElementList.end() && theirIter != rhs.mElementList.end(); ++myIter, ++theirIter) |
188 | { |
189 | if (!(*myIter == *theirIter)) |
190 | return false; |
191 | } |
192 | |
193 | return true; |
194 | } |
195 | |
196 | bool VertexDeclarationProperties::operator!= (const VertexDeclarationProperties& rhs) const |
197 | { |
198 | return !(*this == rhs); |
199 | } |
200 | |
201 | const VertexElement* VertexDeclarationProperties::getElement(UINT16 index) const |
202 | { |
203 | assert(index < mElementList.size() && "Index out of bounds" ); |
204 | |
205 | auto iter = mElementList.begin(); |
206 | for (UINT16 i = 0; i < index; ++i) |
207 | ++iter; |
208 | |
209 | return &(*iter); |
210 | |
211 | } |
212 | |
213 | const VertexElement* VertexDeclarationProperties::findElementBySemantic(VertexElementSemantic sem, UINT16 index) const |
214 | { |
215 | for (auto& elem : mElementList) |
216 | { |
217 | if (elem.getSemantic() == sem && elem.getSemanticIdx() == index) |
218 | { |
219 | return &elem; |
220 | } |
221 | } |
222 | |
223 | return nullptr; |
224 | } |
225 | |
226 | Vector<VertexElement> VertexDeclarationProperties::findElementsBySource(UINT16 source) const |
227 | { |
228 | Vector<VertexElement> retList; |
229 | for (auto& elem : mElementList) |
230 | { |
231 | if (elem.getStreamIdx() == source) |
232 | retList.push_back(elem); |
233 | } |
234 | |
235 | return retList; |
236 | } |
237 | |
238 | UINT32 VertexDeclarationProperties::getVertexSize(UINT16 source) const |
239 | { |
240 | UINT32 size = 0; |
241 | |
242 | for (auto& elem : mElementList) |
243 | { |
244 | if (elem.getStreamIdx() == source) |
245 | { |
246 | size += elem.getSize(); |
247 | } |
248 | } |
249 | |
250 | return size; |
251 | } |
252 | |
253 | VertexDeclaration::VertexDeclaration(const Vector<VertexElement>& elements) |
254 | :mProperties(elements) |
255 | { |
256 | |
257 | } |
258 | |
259 | SPtr<ct::VertexDeclaration> VertexDeclaration::getCore() const |
260 | { |
261 | return std::static_pointer_cast<ct::VertexDeclaration>(mCoreSpecific); |
262 | } |
263 | |
264 | SPtr<ct::CoreObject> VertexDeclaration::createCore() const |
265 | { |
266 | return ct::HardwareBufferManager::instance().createVertexDeclarationInternal(mProperties.mElementList); |
267 | } |
268 | |
269 | SPtr<VertexDeclaration> VertexDeclaration::create(const SPtr<VertexDataDesc>& desc) |
270 | { |
271 | return HardwareBufferManager::instance().createVertexDeclaration(desc); |
272 | } |
273 | |
274 | /************************************************************************/ |
275 | /* SERIALIZATION */ |
276 | /************************************************************************/ |
277 | RTTITypeBase* VertexDeclaration::getRTTIStatic() |
278 | { |
279 | return VertexDeclarationRTTI::instance(); |
280 | } |
281 | |
282 | RTTITypeBase* VertexDeclaration::getRTTI() const |
283 | { |
284 | return getRTTIStatic(); |
285 | } |
286 | |
287 | String toString(const VertexElementSemantic& val) |
288 | { |
289 | switch (val) |
290 | { |
291 | case VES_POSITION: |
292 | return "POSITION" ; |
293 | case VES_BLEND_WEIGHTS: |
294 | return "BLEND_WEIGHTS" ; |
295 | case VES_BLEND_INDICES: |
296 | return "BLEND_INDICES" ; |
297 | case VES_NORMAL: |
298 | return "NORMAL" ; |
299 | case VES_COLOR: |
300 | return "COLOR" ; |
301 | case VES_TEXCOORD: |
302 | return "TEXCOORD" ; |
303 | case VES_BITANGENT: |
304 | return "BITANGENT" ; |
305 | case VES_TANGENT: |
306 | return "TANGENT" ; |
307 | case VES_POSITIONT: |
308 | return "POSITIONT" ; |
309 | case VES_PSIZE: |
310 | return "PSIZE" ; |
311 | } |
312 | |
313 | return "" ; |
314 | } |
315 | |
316 | namespace ct |
317 | { |
318 | UINT32 VertexDeclaration::NextFreeId = 0; |
319 | |
320 | VertexDeclaration::VertexDeclaration(const Vector<VertexElement>& elements, GpuDeviceFlags deviceMask) |
321 | :mProperties(elements) |
322 | { |
323 | |
324 | } |
325 | |
326 | void VertexDeclaration::initialize() |
327 | { |
328 | mId = NextFreeId++; |
329 | CoreObject::initialize(); |
330 | } |
331 | |
332 | SPtr<VertexDeclaration> VertexDeclaration::create(const SPtr<VertexDataDesc>& desc, GpuDeviceFlags deviceMask) |
333 | { |
334 | return HardwareBufferManager::instance().createVertexDeclaration(desc, deviceMask); |
335 | } |
336 | |
337 | bool VertexDeclaration::isCompatible(const SPtr<VertexDeclaration>& shaderDecl) |
338 | { |
339 | const Vector<VertexElement>& shaderElems = shaderDecl->getProperties().getElements(); |
340 | const Vector<VertexElement>& bufferElems = getProperties().getElements(); |
341 | |
342 | for (auto shaderIter = shaderElems.begin(); shaderIter != shaderElems.end(); ++shaderIter) |
343 | { |
344 | const VertexElement* foundElement = nullptr; |
345 | for (auto bufferIter = bufferElems.begin(); bufferIter != bufferElems.end(); ++bufferIter) |
346 | { |
347 | if (shaderIter->getSemantic() == bufferIter->getSemantic() && shaderIter->getSemanticIdx() == bufferIter->getSemanticIdx()) |
348 | { |
349 | foundElement = &(*bufferIter); |
350 | break; |
351 | } |
352 | } |
353 | |
354 | if (foundElement == nullptr) |
355 | return false; |
356 | } |
357 | |
358 | return true; |
359 | } |
360 | |
361 | Vector<VertexElement> VertexDeclaration::getMissingElements(const SPtr<VertexDeclaration>& shaderDecl) |
362 | { |
363 | Vector<VertexElement> missingElements; |
364 | |
365 | const Vector<VertexElement>& shaderElems = shaderDecl->getProperties().getElements(); |
366 | const Vector<VertexElement>& bufferElems = getProperties().getElements(); |
367 | |
368 | for (auto shaderIter = shaderElems.begin(); shaderIter != shaderElems.end(); ++shaderIter) |
369 | { |
370 | const VertexElement* foundElement = nullptr; |
371 | for (auto bufferIter = bufferElems.begin(); bufferIter != bufferElems.end(); ++bufferIter) |
372 | { |
373 | if (shaderIter->getSemantic() == bufferIter->getSemantic() && shaderIter->getSemanticIdx() == bufferIter->getSemanticIdx()) |
374 | { |
375 | foundElement = &(*bufferIter); |
376 | break; |
377 | } |
378 | } |
379 | |
380 | if (foundElement == nullptr) |
381 | missingElements.push_back(*shaderIter); |
382 | } |
383 | |
384 | return missingElements; |
385 | } |
386 | } |
387 | } |