1 #include "precompiled.h"
2 //
3 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7
8 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
9
10 #include "libGLESv2/renderer/VertexBuffer9.h"
11 #include "libGLESv2/renderer/vertexconversion.h"
12 #include "libGLESv2/renderer/BufferStorage.h"
13 #include "libGLESv2/Context.h"
14 #include "libGLESv2/renderer/Renderer9.h"
15
16 #include "libGLESv2/Buffer.h"
17
18 namespace rx
19 {
20
21 bool VertexBuffer9::mTranslationsInitialized = false;
22 VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
23
VertexBuffer9(rx::Renderer9 * const renderer)24 VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
25 {
26 mVertexBuffer = NULL;
27 mBufferSize = 0;
28 mDynamicUsage = false;
29
30 if (!mTranslationsInitialized)
31 {
32 initializeTranslations(renderer->getCapsDeclTypes());
33 mTranslationsInitialized = true;
34 }
35 }
36
~VertexBuffer9()37 VertexBuffer9::~VertexBuffer9()
38 {
39 if (mVertexBuffer)
40 {
41 mVertexBuffer->Release();
42 mVertexBuffer = NULL;
43 }
44 }
45
initialize(unsigned int size,bool dynamicUsage)46 bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
47 {
48 if (mVertexBuffer)
49 {
50 mVertexBuffer->Release();
51 mVertexBuffer = NULL;
52 }
53
54 updateSerial();
55
56 if (size > 0)
57 {
58 DWORD flags = D3DUSAGE_WRITEONLY;
59 if (dynamicUsage)
60 {
61 flags |= D3DUSAGE_DYNAMIC;
62 }
63
64 HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
65
66 if (FAILED(result))
67 {
68 ERR("Out of memory allocating a vertex buffer of size %lu.", size);
69 return false;
70 }
71 }
72
73 mBufferSize = size;
74 mDynamicUsage = dynamicUsage;
75 return true;
76 }
77
makeVertexBuffer9(VertexBuffer * vertexBuffer)78 VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
79 {
80 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
81 return static_cast<VertexBuffer9*>(vertexBuffer);
82 }
83
storeVertexAttributes(const gl::VertexAttribute & attrib,GLint start,GLsizei count,GLsizei instances,unsigned int offset)84 bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
85 GLsizei instances, unsigned int offset)
86 {
87 if (mVertexBuffer)
88 {
89 gl::Buffer *buffer = attrib.mBoundBuffer.get();
90
91 int inputStride = attrib.stride();
92 int elementSize = attrib.typeSize();
93 const FormatConverter &converter = formatConverter(attrib);
94
95 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
96
97 void *mapPtr = NULL;
98
99 unsigned int mapSize;
100 if (!spaceRequired(attrib, count, instances, &mapSize))
101 {
102 return false;
103 }
104
105 HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags);
106
107 if (FAILED(result))
108 {
109 ERR("Lock failed with error 0x%08x", result);
110 return false;
111 }
112
113 const char *input = NULL;
114 if (buffer)
115 {
116 BufferStorage *storage = buffer->getStorage();
117 input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
118 }
119 else
120 {
121 input = static_cast<const char*>(attrib.mPointer);
122 }
123
124 if (instances == 0 || attrib.mDivisor == 0)
125 {
126 input += inputStride * start;
127 }
128
129 if (converter.identity && inputStride == elementSize)
130 {
131 memcpy(mapPtr, input, count * inputStride);
132 }
133 else
134 {
135 converter.convertArray(input, inputStride, count, mapPtr);
136 }
137
138 mVertexBuffer->Unlock();
139
140 return true;
141 }
142 else
143 {
144 ERR("Vertex buffer not initialized.");
145 return false;
146 }
147 }
148
storeRawData(const void * data,unsigned int size,unsigned int offset)149 bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset)
150 {
151 if (mVertexBuffer)
152 {
153 DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
154
155 void *mapPtr = NULL;
156 HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags);
157
158 if (FAILED(result))
159 {
160 ERR("Lock failed with error 0x%08x", result);
161 return false;
162 }
163
164 memcpy(mapPtr, data, size);
165
166 mVertexBuffer->Unlock();
167
168 return true;
169 }
170 else
171 {
172 ERR("Vertex buffer not initialized.");
173 return false;
174 }
175 }
176
getSpaceRequired(const gl::VertexAttribute & attrib,GLsizei count,GLsizei instances,unsigned int * outSpaceRequired) const177 bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
178 unsigned int *outSpaceRequired) const
179 {
180 return spaceRequired(attrib, count, instances, outSpaceRequired);
181 }
182
requiresConversion(const gl::VertexAttribute & attrib) const183 bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
184 {
185 return !formatConverter(attrib).identity;
186 }
187
getVertexSize(const gl::VertexAttribute & attrib) const188 unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
189 {
190 unsigned int spaceRequired;
191 return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0;
192 }
193
getDeclType(const gl::VertexAttribute & attrib) const194 D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
195 {
196 return formatConverter(attrib).d3dDeclType;
197 }
198
getBufferSize() const199 unsigned int VertexBuffer9::getBufferSize() const
200 {
201 return mBufferSize;
202 }
203
setBufferSize(unsigned int size)204 bool VertexBuffer9::setBufferSize(unsigned int size)
205 {
206 if (size > mBufferSize)
207 {
208 return initialize(size, mDynamicUsage);
209 }
210 else
211 {
212 return true;
213 }
214 }
215
discard()216 bool VertexBuffer9::discard()
217 {
218 if (mVertexBuffer)
219 {
220 void *dummy;
221 HRESULT result;
222
223 result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
224 if (FAILED(result))
225 {
226 ERR("Discard lock failed with error 0x%08x", result);
227 return false;
228 }
229
230 result = mVertexBuffer->Unlock();
231 if (FAILED(result))
232 {
233 ERR("Discard unlock failed with error 0x%08x", result);
234 return false;
235 }
236
237 return true;
238 }
239 else
240 {
241 ERR("Vertex buffer not initialized.");
242 return false;
243 }
244 }
245
getBuffer() const246 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
247 {
248 return mVertexBuffer;
249 }
250
251 // Mapping from OpenGL-ES vertex attrib type to D3D decl type:
252 //
253 // BYTE SHORT (Cast)
254 // BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
255 // UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
256 // UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
257 // SHORT SHORT (Identity)
258 // SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
259 // UNSIGNED_SHORT FLOAT (Cast)
260 // UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
261 // FIXED (not in WebGL) FLOAT (FixedToFloat)
262 // FLOAT FLOAT (Identity)
263
264 // GLToCType maps from GL type (as GLenum) to the C typedef.
265 template <GLenum GLType> struct GLToCType { };
266
267 template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
268 template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
269 template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
270 template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
271 template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
272 template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
273
274 // This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
275 enum D3DVertexType
276 {
277 D3DVT_FLOAT,
278 D3DVT_SHORT,
279 D3DVT_SHORT_NORM,
280 D3DVT_UBYTE,
281 D3DVT_UBYTE_NORM,
282 D3DVT_USHORT_NORM
283 };
284
285 // D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
286 template <unsigned int D3DType> struct D3DToCType { };
287
288 template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
289 template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
290 template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
291 template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
292 template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
293 template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
294
295 // Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
296 template <unsigned int type, int size> struct WidenRule { };
297
298 template <int size> struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> { };
299 template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { };
300 template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { };
301 template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { };
302 template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { };
303 template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> { };
304
305 // VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
306 template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
307
308 template <unsigned int _capflag, unsigned int _declflag>
309 struct VertexTypeFlagsHelper
310 {
311 enum { capflag = _capflag };
312 enum { declflag = _declflag };
313 };
314
315 template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
316 template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
317 template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
318 template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
319 template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
320 template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
321 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
322 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
323 template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
324 template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
325 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
326 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
327
328
329 // VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
330 template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
331
332 template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
333 struct VertexTypeMappingBase
334 {
335 enum { preferred = Preferred };
336 enum { fallback = Fallback };
337 };
338
339 template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast
340 template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize
341 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast
342 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize
343 template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity
344 template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
345 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast
346 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
347 template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat
348 template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity
349
350
351 // Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
352 // The conversion rules themselves are defined in vertexconversion.h.
353
354 // Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
355 template <GLenum fromType, bool normalized, unsigned int toType>
356 struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
357
358 // All conversions from normalized types to float use the Normalize operator.
359 template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
360
361 // Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
362 template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
363 template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
364
365 // A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
366 // whether it is normalized or not.
367 template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
368
369 template <class T> struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> { };
370 template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
371
372 // Work out the default value rule for a D3D type (expressed as the C type) and
373 template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
374 template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
375
376 // Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
377 // The fallback conversion produces an output that all D3D9 devices must support.
378 template <class T> struct UsePreferred { enum { type = T::preferred }; };
379 template <class T> struct UseFallback { enum { type = T::fallback }; };
380
381 // Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
382 // it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
383 // and the D3DDECLTYPE member needed for the vertex declaration in declflag.
384 template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
385 struct Converter
386 : VertexDataConverter<typename GLToCType<fromType>::type,
387 WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
388 ConversionRule<fromType,
389 normalized,
390 PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
391 DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
392 {
393 private:
394 enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
395 enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
396
397 public:
398 enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
399 enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
400 };
401
402 // Initialize a TranslationInfo
403 #define TRANSLATION(type, norm, size, preferred) \
404 { \
405 Converter<type, norm, size, preferred>::identity, \
406 Converter<type, norm, size, preferred>::finalSize, \
407 Converter<type, norm, size, preferred>::convertArray, \
408 static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \
409 }
410
411 #define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
412 { \
413 Converter<type, norm, size, UsePreferred>::capflag, \
414 TRANSLATION(type, norm, size, UsePreferred), \
415 TRANSLATION(type, norm, size, UseFallback) \
416 }
417
418 #define TRANSLATIONS_FOR_TYPE(type) \
419 { \
420 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
421 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \
422 }
423
424 #define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \
425 { \
426 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
427 { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
428 }
429
430 const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
431 {
432 TRANSLATIONS_FOR_TYPE(GL_BYTE),
433 TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
434 TRANSLATIONS_FOR_TYPE(GL_SHORT),
435 TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
436 TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
437 TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
438 };
439
initializeTranslations(DWORD declTypes)440 void VertexBuffer9::initializeTranslations(DWORD declTypes)
441 {
442 for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
443 {
444 for (unsigned int j = 0; j < 2; j++)
445 {
446 for (unsigned int k = 0; k < 4; k++)
447 {
448 if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
449 {
450 mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
451 }
452 else
453 {
454 mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
455 }
456 }
457 }
458 }
459 }
460
typeIndex(GLenum type)461 unsigned int VertexBuffer9::typeIndex(GLenum type)
462 {
463 switch (type)
464 {
465 case GL_BYTE: return 0;
466 case GL_UNSIGNED_BYTE: return 1;
467 case GL_SHORT: return 2;
468 case GL_UNSIGNED_SHORT: return 3;
469 case GL_FIXED: return 4;
470 case GL_FLOAT: return 5;
471
472 default: UNREACHABLE(); return 5;
473 }
474 }
475
formatConverter(const gl::VertexAttribute & attribute)476 const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
477 {
478 return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
479 }
480
spaceRequired(const gl::VertexAttribute & attrib,std::size_t count,GLsizei instances,unsigned int * outSpaceRequired)481 bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
482 unsigned int *outSpaceRequired)
483 {
484 unsigned int elementSize = formatConverter(attrib).outputElementSize;
485
486 if (attrib.mArrayEnabled)
487 {
488 unsigned int elementCount = 0;
489 if (instances == 0 || attrib.mDivisor == 0)
490 {
491 elementCount = count;
492 }
493 else
494 {
495 if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
496 {
497 // Round up
498 elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
499 }
500 else
501 {
502 elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor;
503 }
504 }
505
506 if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
507 {
508 if (outSpaceRequired)
509 {
510 *outSpaceRequired = elementSize * elementCount;
511 }
512 return true;
513 }
514 else
515 {
516 return false;
517 }
518 }
519 else
520 {
521 const unsigned int elementSize = 4;
522 if (outSpaceRequired)
523 {
524 *outSpaceRequired = elementSize * 4;
525 }
526 return true;
527 }
528 }
529
530 }
531