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 "tcuFloat.hpp"
35 #include "tcuPixelFormat.hpp"
36 #include "sglrContext.hpp"
37 
38 namespace sglr
39 {
40 
41 class ReferenceContextBuffers;
42 class ReferenceContext;
43 class Context;
44 
45 } // sglr
46 
47 namespace deqp
48 {
49 namespace gls
50 {
51 
52 class Array
53 {
54 public:
55 	enum Target
56 	{
57 		// \note [mika] Are these actualy used somewhere?
58 		TARGET_ELEMENT_ARRAY = 0,
59 		TARGET_ARRAY,
60 
61 		TARGET_LAST
62 	};
63 
64 	enum InputType
65 	{
66 		INPUTTYPE_FLOAT = 0,
67 		INPUTTYPE_FIXED,
68 		INPUTTYPE_DOUBLE,
69 
70 		INPUTTYPE_BYTE,
71 		INPUTTYPE_SHORT,
72 
73 		INPUTTYPE_UNSIGNED_BYTE,
74 		INPUTTYPE_UNSIGNED_SHORT,
75 
76 		INPUTTYPE_INT,
77 		INPUTTYPE_UNSIGNED_INT,
78 		INPUTTYPE_HALF,
79 		INPUTTYPE_UNSIGNED_INT_2_10_10_10,
80 		INPUTTYPE_INT_2_10_10_10,
81 
82 		INPUTTYPE_LAST
83 	};
84 
85 	enum OutputType
86 	{
87 		OUTPUTTYPE_FLOAT = 0,
88 		OUTPUTTYPE_VEC2,
89 		OUTPUTTYPE_VEC3,
90 		OUTPUTTYPE_VEC4,
91 
92 		OUTPUTTYPE_INT,
93 		OUTPUTTYPE_UINT,
94 
95 		OUTPUTTYPE_IVEC2,
96 		OUTPUTTYPE_IVEC3,
97 		OUTPUTTYPE_IVEC4,
98 
99 		OUTPUTTYPE_UVEC2,
100 		OUTPUTTYPE_UVEC3,
101 		OUTPUTTYPE_UVEC4,
102 
103 		OUTPUTTYPE_LAST
104 	};
105 
106 	enum Usage
107 	{
108 		USAGE_DYNAMIC_DRAW = 0,
109 		USAGE_STATIC_DRAW,
110 		USAGE_STREAM_DRAW,
111 
112 		USAGE_STREAM_READ,
113 		USAGE_STREAM_COPY,
114 
115 		USAGE_STATIC_READ,
116 		USAGE_STATIC_COPY,
117 
118 		USAGE_DYNAMIC_READ,
119 		USAGE_DYNAMIC_COPY,
120 
121 		USAGE_LAST
122 	};
123 
124 	enum Storage
125 	{
126 		STORAGE_USER = 0,
127 		STORAGE_BUFFER,
128 
129 		STORAGE_LAST
130 	};
131 
132 	enum Primitive
133 	{
134 		PRIMITIVE_POINTS = 0,
135 		PRIMITIVE_TRIANGLES,
136 		PRIMITIVE_TRIANGLE_FAN,
137 		PRIMITIVE_TRIANGLE_STRIP,
138 
139 		PRIMITIVE_LAST
140 	};
141 
142 	static std::string	targetToString		(Target target);
143 	static std::string	inputTypeToString	(InputType type);
144 	static std::string	outputTypeToString	(OutputType type);
145 	static std::string	usageTypeToString	(Usage usage);
146 	static std::string	storageToString		(Storage storage);
147 	static std::string	primitiveToString	(Primitive primitive);
148 	static int			inputTypeSize		(InputType type);
149 
~Array(void)150 	virtual				~Array				(void) {}
151 	virtual void		data				(Target target, int size, const char* data, Usage usage) = 0;
152 	virtual void		subdata				(Target target, int offset, int size, const char* data) = 0;
153 	virtual void		bind				(int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride) = 0;
154 	virtual void		unBind				(void) = 0;
155 
156 	virtual bool		isBound				(void) const = 0;
157 	virtual int			getComponentCount	(void) const = 0;
158 	virtual Target		getTarget			(void) const = 0;
159 	virtual InputType	getInputType		(void) const = 0;
160 	virtual OutputType	getOutputType		(void) const = 0;
161 	virtual Storage		getStorageType		(void) const = 0;
162 	virtual bool		getNormalized		(void) const = 0;
163 	virtual int			getStride			(void) const = 0;
164 	virtual int			getAttribNdx		(void) const = 0;
165 	virtual void		setAttribNdx		(int attribNdx) = 0;
166 };
167 
168 class ContextArray : public Array
169 {
170 public:
171 								ContextArray		(Storage storage, sglr::Context& context);
172 	virtual						~ContextArray		(void);
173 	virtual void				data				(Target target, int size, const char* data, Usage usage);
174 	virtual void				subdata				(Target target, int offset, int size, const char* data);
175 	virtual void				bind				(int attribNdx, int offset, int size, InputType inType, OutputType outType, bool normalized, int stride);
176 	virtual void				bindIndexArray		(Array::Target storage);
unBind(void)177 	virtual void				unBind				(void) { m_bound = false; }
isBound(void) const178 	virtual bool				isBound				(void) const { return m_bound; }
179 
getComponentCount(void) const180 	virtual int					getComponentCount	(void) const { return m_componentCount; }
getTarget(void) const181 	virtual Array::Target		getTarget			(void) const { return m_target; }
getInputType(void) const182 	virtual Array::InputType	getInputType		(void) const { return m_inputType; }
getOutputType(void) const183 	virtual Array::OutputType	getOutputType		(void) const { return m_outputType; }
getStorageType(void) const184 	virtual Array::Storage		getStorageType		(void) const { return m_storage; }
getNormalized(void) const185 	virtual bool				getNormalized		(void) const { return m_normalize; }
getStride(void) const186 	virtual int					getStride			(void) const { return m_stride; }
getAttribNdx(void) const187 	virtual int					getAttribNdx		(void) const { return m_attribNdx; }
setAttribNdx(int attribNdx)188 	virtual void				setAttribNdx		(int attribNdx) { m_attribNdx = attribNdx; }
189 
190 	void						glBind				(deUint32 loc);
191 	static deUint32				targetToGL			(Array::Target target);
192 	static deUint32				usageToGL			(Array::Usage usage);
193 	static deUint32				inputTypeToGL		(Array::InputType type);
194 	static std::string			outputTypeToGLType	(Array::OutputType type);
195 	static deUint32				primitiveToGL		(Array::Primitive primitive);
196 
197 private:
198 	Storage						m_storage;
199 	sglr::Context&				m_ctx;
200 	deUint32					m_glBuffer;
201 
202 	bool						m_bound;
203 	int							m_attribNdx;
204 	int							m_size;
205 	char*						m_data;
206 	int							m_componentCount;
207 	Array::Target				m_target;
208 	Array::InputType			m_inputType;
209 	Array::OutputType			m_outputType;
210 	bool						m_normalize;
211 	int							m_stride;
212 	int							m_offset;
213 };
214 
215 class ContextArrayPack
216 {
217 public:
218 								ContextArrayPack	(glu::RenderContext& renderCtx, sglr::Context& drawContext);
219 	virtual						~ContextArrayPack	(void);
220 	virtual Array*				getArray			(int i);
221 	virtual int					getArrayCount		(void);
222 	virtual	void				newArray			(Array::Storage storage);
223 	virtual void				render 				(Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, float colorScale);
224 
getSurface(void) const225 	const tcu::Surface&			getSurface			(void) const { return m_screen; }
226 private:
227 	void 						updateProgram		(void);
228 	glu::RenderContext&			m_renderCtx;
229 	sglr::Context&				m_ctx;
230 
231 	std::vector<ContextArray*>	m_arrays;
232 	sglr::ShaderProgram*		m_program;
233 	tcu::Surface				m_screen;
234 };
235 
236 class GLValue
237 {
238 public:
239 
240 	template<class Type>
241 	class WrappedType
242 	{
243 	public:
create(Type value)244 		static WrappedType<Type>	create			(Type value)							{ WrappedType<Type> v; v.m_value = value; return v; }
getValue(void) const245 		inline Type					getValue		(void) const							{ return m_value; }
246 
operator +(const WrappedType<Type> & other) const247 		inline WrappedType<Type>	operator+		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value + other.getValue()); }
operator *(const WrappedType<Type> & other) const248 		inline WrappedType<Type>	operator*		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value * other.getValue()); }
operator /(const WrappedType<Type> & other) const249 		inline WrappedType<Type>	operator/		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value / other.getValue()); }
operator -(const WrappedType<Type> & other) const250 		inline WrappedType<Type>	operator-		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create(m_value - other.getValue()); }
251 
operator +=(const WrappedType<Type> & other)252 		inline WrappedType<Type>&	operator+=		(const WrappedType<Type>& other)		{ m_value += other.getValue(); return *this; }
operator *=(const WrappedType<Type> & other)253 		inline WrappedType<Type>&	operator*=		(const WrappedType<Type>& other)		{ m_value *= other.getValue(); return *this; }
operator /=(const WrappedType<Type> & other)254 		inline WrappedType<Type>&	operator/=		(const WrappedType<Type>& other)		{ m_value /= other.getValue(); return *this; }
operator -=(const WrappedType<Type> & other)255 		inline WrappedType<Type>&	operator-=		(const WrappedType<Type>& other)		{ m_value -= other.getValue(); return *this; }
256 
operator ==(const WrappedType<Type> & other) const257 		inline bool					operator==		(const WrappedType<Type>& other) const	{ return m_value == other.m_value; }
operator !=(const WrappedType<Type> & other) const258 		inline bool					operator!=		(const WrappedType<Type>& other) const	{ return m_value != other.m_value; }
operator <(const WrappedType<Type> & other) const259 		inline bool					operator<		(const WrappedType<Type>& other) const	{ return m_value < other.m_value; }
operator >(const WrappedType<Type> & other) const260 		inline bool					operator>		(const WrappedType<Type>& other) const	{ return m_value > other.m_value; }
operator <=(const WrappedType<Type> & other) const261 		inline bool					operator<=		(const WrappedType<Type>& other) const	{ return m_value <= other.m_value; }
operator >=(const WrappedType<Type> & other) const262 		inline bool					operator>=		(const WrappedType<Type>& other) const	{ return m_value >= other.m_value; }
263 
operator Type(void) const264 		inline 						operator Type	(void) const							{ return m_value; }
265 		template<class T>
to(void) const266 		inline T					to				(void) const							{ return (T)m_value; }
267 	private:
268 		Type	m_value;
269 	};
270 
271 	typedef WrappedType<deInt16>	Short;
272 	typedef WrappedType<deUint16>	Ushort;
273 
274 	typedef WrappedType<deInt8>		Byte;
275 	typedef WrappedType<deUint8>	Ubyte;
276 
277 	typedef WrappedType<float>		Float;
278 	typedef WrappedType<double>		Double;
279 
280 	typedef WrappedType<deInt32>	Int;
281 	typedef WrappedType<deUint32>	Uint;
282 
283 	class Half
284 	{
285 	public:
create(float value)286 		static Half			create			(float value)				{ Half h; h.m_value = floatToHalf(value); return h; }
getValue(void) const287 		inline deFloat16	getValue		(void) const				{ return m_value; }
288 
operator +(const Half & other) const289 		inline Half			operator+		(const Half& other) const	{ return create(halfToFloat(m_value) + halfToFloat(other.getValue())); }
operator *(const Half & other) const290 		inline Half			operator*		(const Half& other) const	{ return create(halfToFloat(m_value) * halfToFloat(other.getValue())); }
operator /(const Half & other) const291 		inline Half			operator/		(const Half& other) const	{ return create(halfToFloat(m_value) / halfToFloat(other.getValue())); }
operator -(const Half & other) const292 		inline Half			operator-		(const Half& other) const	{ return create(halfToFloat(m_value) - halfToFloat(other.getValue())); }
293 
operator +=(const Half & other)294 		inline Half&		operator+=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) + halfToFloat(m_value)); return *this; }
operator *=(const Half & other)295 		inline Half&		operator*=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) * halfToFloat(m_value)); return *this; }
operator /=(const Half & other)296 		inline Half&		operator/=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) / halfToFloat(m_value)); return *this; }
operator -=(const Half & other)297 		inline Half&		operator-=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) - halfToFloat(m_value)); return *this; }
298 
operator ==(const Half & other) const299 		inline bool			operator==		(const Half& other) const	{ return m_value == other.m_value; }
operator !=(const Half & other) const300 		inline bool			operator!=		(const Half& other) const	{ return m_value != other.m_value; }
operator <(const Half & other) const301 		inline bool			operator<		(const Half& other) const	{ return halfToFloat(m_value) < halfToFloat(other.m_value); }
operator >(const Half & other) const302 		inline bool			operator>		(const Half& other) const	{ return halfToFloat(m_value) > halfToFloat(other.m_value); }
operator <=(const Half & other) const303 		inline bool			operator<=		(const Half& other) const	{ return halfToFloat(m_value) <= halfToFloat(other.m_value); }
operator >=(const Half & other) const304 		inline bool			operator>=		(const Half& other) const	{ return halfToFloat(m_value) >= halfToFloat(other.m_value); }
305 
306 		template<class T>
to(void) const307 		inline T			to				(void) const				{ return (T)halfToFloat(m_value); }
308 
309 		inline static deFloat16	floatToHalf		(float f);
310 		inline static float		halfToFloat		(deFloat16 h);
311 	private:
312 		deFloat16 m_value;
313 	};
314 
315 	class Fixed
316 	{
317 	public:
create(deInt32 value)318 		static Fixed		create			(deInt32 value)				{ Fixed v; v.m_value = value; return v; }
getValue(void) const319 		inline deInt32		getValue		(void) const				{ return m_value; }
320 
operator +(const Fixed & other) const321 		inline Fixed		operator+		(const Fixed& other) const	{ return create(m_value + other.getValue()); }
operator *(const Fixed & other) const322 		inline Fixed		operator*		(const Fixed& other) const	{ return create(m_value * other.getValue()); }
operator /(const Fixed & other) const323 		inline Fixed		operator/		(const Fixed& other) const	{ return create(m_value / other.getValue()); }
operator -(const Fixed & other) const324 		inline Fixed		operator-		(const Fixed& other) const	{ return create(m_value - other.getValue()); }
325 
operator +=(const Fixed & other)326 		inline Fixed&		operator+=		(const Fixed& other)		{ m_value += other.getValue(); return *this; }
operator *=(const Fixed & other)327 		inline Fixed&		operator*=		(const Fixed& other)		{ m_value *= other.getValue(); return *this; }
operator /=(const Fixed & other)328 		inline Fixed&		operator/=		(const Fixed& other)		{ m_value /= other.getValue(); return *this; }
operator -=(const Fixed & other)329 		inline Fixed&		operator-=		(const Fixed& other)		{ m_value -= other.getValue(); return *this; }
330 
operator ==(const Fixed & other) const331 		inline bool			operator==		(const Fixed& other) const	{ return m_value == other.m_value; }
operator !=(const Fixed & other) const332 		inline bool			operator!=		(const Fixed& other) const	{ return m_value != other.m_value; }
operator <(const Fixed & other) const333 		inline bool			operator<		(const Fixed& other) const	{ return m_value < other.m_value; }
operator >(const Fixed & other) const334 		inline bool			operator>		(const Fixed& other) const	{ return m_value > other.m_value; }
operator <=(const Fixed & other) const335 		inline bool			operator<=		(const Fixed& other) const	{ return m_value <= other.m_value; }
operator >=(const Fixed & other) const336 		inline bool			operator>=		(const Fixed& other) const	{ return m_value >= other.m_value; }
337 
operator deInt32(void) const338 		inline 				operator deInt32 (void) const				{ return m_value; }
339 		template<class T>
to(void) const340 		inline T			to				(void) const				{ return (T)m_value; }
341 	private:
342 		deInt32				m_value;
343 	};
344 
345 	// \todo [mika] This is pretty messy
GLValue(void)346 						GLValue			(void)			: type(Array::INPUTTYPE_LAST) {}
GLValue(Float value)347 	explicit			GLValue			(Float value)	: type(Array::INPUTTYPE_FLOAT),				fl(value)	{}
GLValue(Fixed value)348 	explicit			GLValue			(Fixed value)	: type(Array::INPUTTYPE_FIXED),				fi(value)	{}
GLValue(Byte value)349 	explicit			GLValue			(Byte value)	: type(Array::INPUTTYPE_BYTE),				b(value)	{}
GLValue(Ubyte value)350 	explicit			GLValue			(Ubyte value)	: type(Array::INPUTTYPE_UNSIGNED_BYTE),		ub(value)	{}
GLValue(Short value)351 	explicit			GLValue			(Short value)	: type(Array::INPUTTYPE_SHORT),				s(value)	{}
GLValue(Ushort value)352 	explicit			GLValue			(Ushort value)	: type(Array::INPUTTYPE_UNSIGNED_SHORT),	us(value)	{}
GLValue(Int value)353 	explicit			GLValue			(Int value)		: type(Array::INPUTTYPE_INT),				i(value)	{}
GLValue(Uint value)354 	explicit			GLValue			(Uint value)	: type(Array::INPUTTYPE_UNSIGNED_INT),		ui(value)	{}
GLValue(Half value)355 	explicit			GLValue			(Half value)	: type(Array::INPUTTYPE_HALF),				h(value)	{}
GLValue(Double value)356 	explicit			GLValue			(Double value)	: type(Array::INPUTTYPE_DOUBLE),			d(value)	{}
357 
358 	float				toFloat			(void) const;
359 
360 	static GLValue		getMaxValue		(Array::InputType type);
361 	static GLValue		getMinValue		(Array::InputType type);
362 
363 	Array::InputType	type;
364 
365 	union
366 	{
367 		Float		fl;
368 		Fixed		fi;
369 		Double		d;
370 		Byte		b;
371 		Ubyte		ub;
372 		Short		s;
373 		Ushort		us;
374 		Int			i;
375 		Uint		ui;
376 		Half		h;
377 	};
378 };
379 
380 class VertexArrayTest : public tcu::TestCase
381 {
382 public:
383 									VertexArrayTest		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name ,const char* desc);
384 	virtual							~VertexArrayTest	(void);
385 	virtual void					init				(void);
386 	virtual void					deinit				(void);
387 
388 protected:
389 									VertexArrayTest		(const VertexArrayTest& other);
390 	VertexArrayTest&				operator=			(const VertexArrayTest& other);
391 
392 	void							compare				(void);
393 
394 	glu::RenderContext&				m_renderCtx;
395 
396 	sglr::ReferenceContextBuffers*	m_refBuffers;
397 	sglr::ReferenceContext*			m_refContext;
398 	sglr::Context*					m_glesContext;
399 
400 	ContextArrayPack*				m_glArrayPack;
401 	ContextArrayPack*				m_rrArrayPack;
402 	bool							m_isOk;
403 
404 	int								m_maxDiffRed;
405 	int								m_maxDiffGreen;
406 	int								m_maxDiffBlue;
407 };
408 
409 class MultiVertexArrayTest : public VertexArrayTest
410 {
411 public:
412 	class Spec
413 	{
414 	public:
415 		class ArraySpec
416 		{
417 		public:
418 								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);
419 
420 			Array::InputType	inputType;
421 			Array::OutputType	outputType;
422 			Array::Storage		storage;
423 			Array::Usage		usage;
424 			int 				componentCount;
425 			int					offset;
426 			int					stride;
427 			bool				normalize;
428 			GLValue				min;
429 			GLValue				max;
430 		};
431 
432 		std::string 			getName		(void) const;
433 		std::string				getDesc		(void) const;
434 
435 		Array::Primitive		primitive;
436 		int						drawCount;			//!<Number of primitives to draw
437 		int						first;
438 
439 		std::vector<ArraySpec>	arrays;
440 	};
441 
442 							MultiVertexArrayTest	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const Spec& spec, const char* name, const char* desc);
443 	virtual					~MultiVertexArrayTest	(void);
444 	virtual IterateResult	iterate					(void);
445 
446 private:
447 	bool					isUnalignedBufferOffsetTest		(void) const;
448 	bool					isUnalignedBufferStrideTest		(void) const;
449 
450 	Spec					m_spec;
451 	int						m_iteration;
452 };
453 
floatToHalf(float f)454 inline deFloat16 GLValue::Half::floatToHalf (float f)
455 {
456 	// No denorm support.
457 	tcu::Float<deUint16, 5, 10, 15, tcu::FLOAT_HAS_SIGN> v(f);
458 	DE_ASSERT(!v.isNaN() && !v.isInf());
459 	return v.bits();
460 }
461 
halfToFloat(deFloat16 h)462 inline float GLValue::Half::halfToFloat (deFloat16 h)
463 {
464 	return tcu::Float16((deUint16)h).asFloat();
465 }
466 
467 } // gls
468 } // deqp
469 
470 #endif // _GLSVERTEXARRAYTESTS_HPP
471