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
39namespace sglr
40{
41
42class ReferenceContextBuffers;
43class ReferenceContext;
44class Context;
45
46} // sglr
47
48namespace deqp
49{
50namespace gls
51{
52
53class Array
54{
55public:
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
169class ContextArray : public Array
170{
171public:
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
198private:
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
216class ContextArrayPack
217{
218public:
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; }
227private:
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
237class GLValue
238{
239public:
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
419class VertexArrayTest : public tcu::TestCase
420{
421public:
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
427protected:
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
448class MultiVertexArrayTest : public VertexArrayTest
449{
450public:
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
485private:
486	bool					isUnalignedBufferOffsetTest		(void) const;
487	bool					isUnalignedBufferStrideTest		(void) const;
488
489	Spec					m_spec;
490	int						m_iteration;
491};
492
493inline 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
501inline 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