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