lin
2025-08-14 dae8bad597b6607a449b32bf76c523423f7720ed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
#ifndef _GLSVERTEXARRAYTESTS_HPP
#define _GLSVERTEXARRAYTESTS_HPP
/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) Module
 * -----------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Vertex array and buffer tests
 *//*--------------------------------------------------------------------*/
 
#include "tcuTestCase.hpp"
#include "tcuVector.hpp"
#include "tcuSurface.hpp"
#include "gluRenderContext.hpp"
#include "gluCallLogWrapper.hpp"
#include "tcuTestLog.hpp"
#include "gluShaderProgram.hpp"
#include "deFloat16.h"
#include "deMath.h"
#include "tcuFloat.hpp"
#include "tcuPixelFormat.hpp"
#include "sglrContext.hpp"
 
namespace sglr
{
 
class ReferenceContextBuffers;
class ReferenceContext;
class Context;
 
} // sglr
 
namespace deqp
{
namespace gls
{
 
class Array
{
public:
   enum Target
   {
       // \note [mika] Are these actualy used somewhere?
       TARGET_ELEMENT_ARRAY = 0,
       TARGET_ARRAY,
 
       TARGET_LAST
   };
 
   enum InputType
   {
       INPUTTYPE_FLOAT = 0,
       INPUTTYPE_FIXED,
       INPUTTYPE_DOUBLE,
 
       INPUTTYPE_BYTE,
       INPUTTYPE_SHORT,
 
       INPUTTYPE_UNSIGNED_BYTE,
       INPUTTYPE_UNSIGNED_SHORT,
 
       INPUTTYPE_INT,
       INPUTTYPE_UNSIGNED_INT,
       INPUTTYPE_HALF,
       INPUTTYPE_UNSIGNED_INT_2_10_10_10,
       INPUTTYPE_INT_2_10_10_10,
 
       INPUTTYPE_LAST
   };
 
   enum OutputType
   {
       OUTPUTTYPE_FLOAT = 0,
       OUTPUTTYPE_VEC2,
       OUTPUTTYPE_VEC3,
       OUTPUTTYPE_VEC4,
 
       OUTPUTTYPE_INT,
       OUTPUTTYPE_UINT,
 
       OUTPUTTYPE_IVEC2,
       OUTPUTTYPE_IVEC3,
       OUTPUTTYPE_IVEC4,
 
       OUTPUTTYPE_UVEC2,
       OUTPUTTYPE_UVEC3,
       OUTPUTTYPE_UVEC4,
 
       OUTPUTTYPE_LAST
   };
 
   enum Usage
   {
       USAGE_DYNAMIC_DRAW = 0,
       USAGE_STATIC_DRAW,
       USAGE_STREAM_DRAW,
 
       USAGE_STREAM_READ,
       USAGE_STREAM_COPY,
 
       USAGE_STATIC_READ,
       USAGE_STATIC_COPY,
 
       USAGE_DYNAMIC_READ,
       USAGE_DYNAMIC_COPY,
 
       USAGE_LAST
   };
 
   enum Storage
   {
       STORAGE_USER = 0,
       STORAGE_BUFFER,
 
       STORAGE_LAST
   };
 
   enum Primitive
   {
       PRIMITIVE_POINTS = 0,
       PRIMITIVE_TRIANGLES,
       PRIMITIVE_TRIANGLE_FAN,
       PRIMITIVE_TRIANGLE_STRIP,
 
       PRIMITIVE_LAST
   };
 
   static std::string    targetToString        (Target target);
   static std::string    inputTypeToString    (InputType type);
   static std::string    outputTypeToString    (OutputType type);
   static std::string    usageTypeToString    (Usage usage);
   static std::string    storageToString        (Storage storage);
   static std::string    primitiveToString    (Primitive primitive);
   static int            inputTypeSize        (InputType type);
 
   virtual                ~Array                (void) {}
   virtual void        data                (Target target, int size, const char* data, Usage usage) = 0;
   virtual void        subdata                (Target target, int offset, int size, const char* data) = 0;
   virtual void        bind                (int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride) = 0;
   virtual void        unBind                (void) = 0;
 
   virtual bool        isBound                (void) const = 0;
   virtual int            getComponentCount    (void) const = 0;
   virtual Target        getTarget            (void) const = 0;
   virtual InputType    getInputType        (void) const = 0;
   virtual OutputType    getOutputType        (void) const = 0;
   virtual Storage        getStorageType        (void) const = 0;
   virtual bool        getNormalized        (void) const = 0;
   virtual int            getStride            (void) const = 0;
   virtual int            getAttribNdx        (void) const = 0;
   virtual void        setAttribNdx        (int attribNdx) = 0;
};
 
class ContextArray : public Array
{
public:
                               ContextArray        (Storage storage, sglr::Context& context);
   virtual                        ~ContextArray        (void);
   virtual void                data                (Target target, int size, const char* data, Usage usage);
   virtual void                subdata                (Target target, int offset, int size, const char* data);
   virtual void                bind                (int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride);
   virtual void                bindIndexArray        (Array::Target storage);
   virtual void                unBind                (void) { m_bound = false; }
   virtual bool                isBound                (void) const { return m_bound; }
 
   virtual int                    getComponentCount    (void) const { return m_componentCount; }
   virtual Array::Target        getTarget            (void) const { return m_target; }
   virtual Array::InputType    getInputType        (void) const { return m_inputType; }
   virtual Array::OutputType    getOutputType        (void) const { return m_outputType; }
   virtual Array::Storage        getStorageType        (void) const { return m_storage; }
   virtual bool                getNormalized        (void) const { return m_normalize; }
   virtual int                    getStride            (void) const { return m_stride; }
   virtual int                    getAttribNdx        (void) const { return m_attribNdx; }
   virtual void                setAttribNdx        (int attribNdx) { m_attribNdx = attribNdx; }
 
   void                        glBind                (deUint32 loc);
   static deUint32                targetToGL            (Array::Target target);
   static deUint32                usageToGL            (Array::Usage usage);
   static deUint32                inputTypeToGL        (Array::InputType type);
   static std::string            outputTypeToGLType    (Array::OutputType type);
   static deUint32                primitiveToGL        (Array::Primitive primitive);
 
private:
   Storage                        m_storage;
   sglr::Context&                m_ctx;
   deUint32                    m_glBuffer;
 
   bool                        m_bound;
   int                            m_attribNdx;
   int                            m_size;
   char*                        m_data;
   int                            m_componentCount;
   Array::Target                m_target;
   Array::InputType            m_inputType;
   Array::OutputType            m_outputType;
   bool                        m_normalize;
   int                            m_stride;
   int                            m_offset;
};
 
class ContextArrayPack
{
public:
                               ContextArrayPack    (glu::RenderContext& renderCtx, sglr::Context& drawContext);
   virtual                        ~ContextArrayPack    (void);
   virtual Array*                getArray            (int i);
   virtual int                    getArrayCount        (void);
   virtual    void                newArray            (Array::Storage storage);
   virtual void                render                (Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, float colorScale);
 
   const tcu::Surface&            getSurface            (void) const { return m_screen; }
private:
   void                        updateProgram        (void);
   glu::RenderContext&            m_renderCtx;
   sglr::Context&                m_ctx;
 
   std::vector<ContextArray*>    m_arrays;
   sglr::ShaderProgram*        m_program;
   tcu::Surface                m_screen;
};
 
class GLValue
{
public:
   template<class Type>
   class WrappedType
   {
   public:
       static WrappedType<Type>    create            (Type value)                            { WrappedType<Type> v; v.m_value = value; return v; }
       static WrappedType<Type>    fromFloat        (float value)                            { WrappedType<Type> v; v.m_value = (Type)value; return v; }
       inline Type                    getValue        (void) const                            { return m_value; }
 
       inline WrappedType<Type>    operator+        (const WrappedType<Type>& other) const    { return WrappedType<Type>::create((Type)(m_value + other.getValue())); }
       inline WrappedType<Type>    operator*        (const WrappedType<Type>& other) const    { return WrappedType<Type>::create((Type)(m_value * other.getValue())); }
       inline WrappedType<Type>    operator/        (const WrappedType<Type>& other) const    { return WrappedType<Type>::create((Type)(m_value / other.getValue())); }
       inline WrappedType<Type>    operator%        (const WrappedType<Type>& other) const    { return WrappedType<Type>::create((Type)(m_value % other.getValue())); }
       inline WrappedType<Type>    operator-        (const WrappedType<Type>& other) const    { return WrappedType<Type>::create((Type)(m_value - other.getValue())); }
 
       inline WrappedType<Type>&    operator+=        (const WrappedType<Type>& other)        { m_value += other.getValue(); return *this; }
       inline WrappedType<Type>&    operator*=        (const WrappedType<Type>& other)        { m_value *= other.getValue(); return *this; }
       inline WrappedType<Type>&    operator/=        (const WrappedType<Type>& other)        { m_value /= other.getValue(); return *this; }
       inline WrappedType<Type>&    operator-=        (const WrappedType<Type>& other)        { m_value -= other.getValue(); return *this; }
 
       inline bool                    operator==        (const WrappedType<Type>& other) const    { return m_value == other.m_value; }
       inline bool                    operator!=        (const WrappedType<Type>& other) const    { return m_value != other.m_value; }
       inline bool                    operator<        (const WrappedType<Type>& other) const    { return m_value < other.m_value; }
       inline bool                    operator>        (const WrappedType<Type>& other) const    { return m_value > other.m_value; }
       inline bool                    operator<=        (const WrappedType<Type>& other) const    { return m_value <= other.m_value; }
       inline bool                    operator>=        (const WrappedType<Type>& other) const    { return m_value >= other.m_value; }
 
       inline                        operator Type    (void) const                            { return m_value; }
       template<class T>
       inline T                    to                (void) const                            { return (T)m_value; }
   private:
       Type    m_value;
   };
 
   template<class Type>
   class WrappedFloatType
   {
   public:
       static WrappedFloatType<Type>    create            (Type value)                            { WrappedFloatType<Type> v; v.m_value = value; return v; }
       static WrappedFloatType<Type>    fromFloat        (float value)                            { WrappedFloatType<Type> v; v.m_value = (Type)value; return v; }
       inline Type                        getValue        (void) const                            { return m_value; }
 
       inline WrappedFloatType<Type>    operator+        (const WrappedFloatType<Type>& other) const    { return WrappedFloatType<Type>::create((Type)(m_value + other.getValue())); }
       inline WrappedFloatType<Type>    operator*        (const WrappedFloatType<Type>& other) const    { return WrappedFloatType<Type>::create((Type)(m_value * other.getValue())); }
       inline WrappedFloatType<Type>    operator/        (const WrappedFloatType<Type>& other) const    { return WrappedFloatType<Type>::create((Type)(m_value / other.getValue())); }
       inline WrappedFloatType<Type>    operator%        (const WrappedFloatType<Type>& other) const    { return WrappedFloatType<Type>::create((Type)(deMod(m_value, other.getValue()))); }
       inline WrappedFloatType<Type>    operator-        (const WrappedFloatType<Type>& other) const    { return WrappedFloatType<Type>::create((Type)(m_value - other.getValue())); }
 
       inline WrappedFloatType<Type>&    operator+=        (const WrappedFloatType<Type>& other)        { m_value += other.getValue(); return *this; }
       inline WrappedFloatType<Type>&    operator*=        (const WrappedFloatType<Type>& other)        { m_value *= other.getValue(); return *this; }
       inline WrappedFloatType<Type>&    operator/=        (const WrappedFloatType<Type>& other)        { m_value /= other.getValue(); return *this; }
       inline WrappedFloatType<Type>&    operator-=        (const WrappedFloatType<Type>& other)        { m_value -= other.getValue(); return *this; }
 
       inline bool                        operator==        (const WrappedFloatType<Type>& other) const    { return m_value == other.m_value; }
       inline bool                        operator!=        (const WrappedFloatType<Type>& other) const    { return m_value != other.m_value; }
       inline bool                        operator<        (const WrappedFloatType<Type>& other) const    { return m_value < other.m_value; }
       inline bool                        operator>        (const WrappedFloatType<Type>& other) const    { return m_value > other.m_value; }
       inline bool                        operator<=        (const WrappedFloatType<Type>& other) const    { return m_value <= other.m_value; }
       inline bool                        operator>=        (const WrappedFloatType<Type>& other) const    { return m_value >= other.m_value; }
 
       inline                            operator Type    (void) const                            { return m_value; }
       template<class T>
       inline T                        to                (void) const                            { return (T)m_value; }
   private:
       Type    m_value;
   };
 
   typedef WrappedType<deInt16>        Short;
   typedef WrappedType<deUint16>        Ushort;
 
   typedef WrappedType<deInt8>            Byte;
   typedef WrappedType<deUint8>        Ubyte;
 
   typedef WrappedFloatType<float>        Float;
   typedef WrappedFloatType<double>    Double;
 
   typedef WrappedType<deInt32>        Int;
   typedef WrappedType<deUint32>        Uint;
 
   class Half
   {
   public:
       static Half            create            (float value)                { Half h; h.m_value = floatToHalf(value); return h; }
       static Half            fromFloat        (float value)                { Half h; h.m_value = floatToHalf(value); return h; }
       inline deFloat16    getValue        (void) const                { return m_value; }
 
       inline Half            operator+        (const Half& other) const    { return create(halfToFloat(m_value) + halfToFloat(other.getValue())); }
       inline Half            operator*        (const Half& other) const    { return create(halfToFloat(m_value) * halfToFloat(other.getValue())); }
       inline Half            operator/        (const Half& other) const    { return create(halfToFloat(m_value) / halfToFloat(other.getValue())); }
       inline Half            operator%        (const Half& other) const    { return create(deFloatMod(halfToFloat(m_value), halfToFloat(other.getValue()))); }
       inline Half            operator-        (const Half& other) const    { return create(halfToFloat(m_value) - halfToFloat(other.getValue())); }
 
       inline Half&        operator+=        (const Half& other)            { m_value = floatToHalf(halfToFloat(other.getValue()) + halfToFloat(m_value)); return *this; }
       inline Half&        operator*=        (const Half& other)            { m_value = floatToHalf(halfToFloat(other.getValue()) * halfToFloat(m_value)); return *this; }
       inline Half&        operator/=        (const Half& other)            { m_value = floatToHalf(halfToFloat(other.getValue()) / halfToFloat(m_value)); return *this; }
       inline Half&        operator-=        (const Half& other)            { m_value = floatToHalf(halfToFloat(other.getValue()) - halfToFloat(m_value)); return *this; }
 
       inline bool            operator==        (const Half& other) const    { return m_value == other.m_value; }
       inline bool            operator!=        (const Half& other) const    { return m_value != other.m_value; }
       inline bool            operator<        (const Half& other) const    { return halfToFloat(m_value) < halfToFloat(other.m_value); }
       inline bool            operator>        (const Half& other) const    { return halfToFloat(m_value) > halfToFloat(other.m_value); }
       inline bool            operator<=        (const Half& other) const    { return halfToFloat(m_value) <= halfToFloat(other.m_value); }
       inline bool            operator>=        (const Half& other) const    { return halfToFloat(m_value) >= halfToFloat(other.m_value); }
 
       template<class T>
       inline T            to                (void) const                { return (T)halfToFloat(m_value); }
 
       inline static deFloat16    floatToHalf        (float f);
       inline static float        halfToFloat        (deFloat16 h);
   private:
       deFloat16 m_value;
   };
 
   class Fixed
   {
   public:
       static Fixed        create            (deInt32 value)                { Fixed v; v.m_value = value; return v; }
       static Fixed        fromFloat        (float value)                { Fixed v; v.m_value = (deInt32)(value * 32768.0f); return v; }
       inline deInt32        getValue        (void) const                { return m_value; }
 
       inline Fixed        operator+        (const Fixed& other) const    { return create(m_value + other.getValue()); }
       inline Fixed        operator*        (const Fixed& other) const    { return create(m_value * other.getValue()); }
       inline Fixed        operator/        (const Fixed& other) const    { return create(m_value / other.getValue()); }
       inline Fixed        operator%        (const Fixed& other) const    { return create(m_value % other.getValue()); }
       inline Fixed        operator-        (const Fixed& other) const    { return create(m_value - other.getValue()); }
 
       inline Fixed&        operator+=        (const Fixed& other)        { m_value += other.getValue(); return *this; }
       inline Fixed&        operator*=        (const Fixed& other)        { m_value *= other.getValue(); return *this; }
       inline Fixed&        operator/=        (const Fixed& other)        { m_value /= other.getValue(); return *this; }
       inline Fixed&        operator-=        (const Fixed& other)        { m_value -= other.getValue(); return *this; }
 
       inline bool            operator==        (const Fixed& other) const    { return m_value == other.m_value; }
       inline bool            operator!=        (const Fixed& other) const    { return m_value != other.m_value; }
       inline bool            operator<        (const Fixed& other) const    { return m_value < other.m_value; }
       inline bool            operator>        (const Fixed& other) const    { return m_value > other.m_value; }
       inline bool            operator<=        (const Fixed& other) const    { return m_value <= other.m_value; }
       inline bool            operator>=        (const Fixed& other) const    { return m_value >= other.m_value; }
 
       inline                operator deInt32 (void) const                { return m_value; }
       template<class T>
       inline T            to                (void) const                { return (T)m_value; }
   private:
       deInt32                m_value;
   };
 
   // \todo [mika] This is pretty messy
                       GLValue            (void)            : type(Array::INPUTTYPE_LAST) {}
   explicit            GLValue            (Float value)    : type(Array::INPUTTYPE_FLOAT),                fl(value)    {}
   explicit            GLValue            (Fixed value)    : type(Array::INPUTTYPE_FIXED),                fi(value)    {}
   explicit            GLValue            (Byte value)    : type(Array::INPUTTYPE_BYTE),                b(value)    {}
   explicit            GLValue            (Ubyte value)    : type(Array::INPUTTYPE_UNSIGNED_BYTE),        ub(value)    {}
   explicit            GLValue            (Short value)    : type(Array::INPUTTYPE_SHORT),                s(value)    {}
   explicit            GLValue            (Ushort value)    : type(Array::INPUTTYPE_UNSIGNED_SHORT),    us(value)    {}
   explicit            GLValue            (Int value)        : type(Array::INPUTTYPE_INT),                i(value)    {}
   explicit            GLValue            (Uint value)    : type(Array::INPUTTYPE_UNSIGNED_INT),        ui(value)    {}
   explicit            GLValue            (Half value)    : type(Array::INPUTTYPE_HALF),                h(value)    {}
   explicit            GLValue            (Double value)    : type(Array::INPUTTYPE_DOUBLE),            d(value)    {}
 
   float                toFloat            (void) const;
 
   static GLValue        getMaxValue        (Array::InputType type);
   static GLValue        getMinValue        (Array::InputType type);
 
   Array::InputType    type;
 
   union
   {
       Float        fl;
       Fixed        fi;
       Double        d;
       Byte        b;
       Ubyte        ub;
       Short        s;
       Ushort        us;
       Int            i;
       Uint        ui;
       Half        h;
   };
};
 
class VertexArrayTest : public tcu::TestCase
{
public:
                                   VertexArrayTest        (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name ,const char* desc);
   virtual                            ~VertexArrayTest    (void);
   virtual void                    init                (void);
   virtual void                    deinit                (void);
 
protected:
                                   VertexArrayTest        (const VertexArrayTest& other);
   VertexArrayTest&                operator=            (const VertexArrayTest& other);
 
   void                            compare                (void);
 
   glu::RenderContext&                m_renderCtx;
 
   sglr::ReferenceContextBuffers*    m_refBuffers;
   sglr::ReferenceContext*            m_refContext;
   sglr::Context*                    m_glesContext;
 
   ContextArrayPack*                m_glArrayPack;
   ContextArrayPack*                m_rrArrayPack;
   bool                            m_isOk;
 
   int                                m_maxDiffRed;
   int                                m_maxDiffGreen;
   int                                m_maxDiffBlue;
};
 
class MultiVertexArrayTest : public VertexArrayTest
{
public:
   class Spec
   {
   public:
       class ArraySpec
       {
       public:
                               ArraySpec    (Array::InputType inputType, Array::OutputType outputType, Array::Storage storage, Array::Usage usage, int componetCount, int offset, int stride, bool normalize, GLValue min, GLValue max);
 
           Array::InputType    inputType;
           Array::OutputType    outputType;
           Array::Storage        storage;
           Array::Usage        usage;
           int                    componentCount;
           int                    offset;
           int                    stride;
           bool                normalize;
           GLValue                min;
           GLValue                max;
       };
 
       std::string                getName        (void) const;
       std::string                getDesc        (void) const;
 
       Array::Primitive        primitive;
       int                        drawCount;            //!<Number of primitives to draw
       int                        first;
 
       std::vector<ArraySpec>    arrays;
   };
 
                           MultiVertexArrayTest    (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const Spec& spec, const char* name, const char* desc);
   virtual                    ~MultiVertexArrayTest    (void);
   virtual IterateResult    iterate                    (void);
 
private:
   bool                    isUnalignedBufferOffsetTest        (void) const;
   bool                    isUnalignedBufferStrideTest        (void) const;
 
   Spec                    m_spec;
   int                        m_iteration;
};
 
inline deFloat16 GLValue::Half::floatToHalf (float f)
{
   // No denorm support.
   tcu::Float<deUint16, 5, 10, 15, tcu::FLOAT_HAS_SIGN> v(f);
   DE_ASSERT(!v.isNaN() && !v.isInf());
   return v.bits();
}
 
inline float GLValue::Half::halfToFloat (deFloat16 h)
{
   return tcu::Float16((deUint16)h).asFloat();
}
 
} // gls
} // deqp
 
#endif // _GLSVERTEXARRAYTESTS_HPP