• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) Module
3  * -----------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Vertex array and buffer tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "glsVertexArrayTests.hpp"
25 
26 #include "deRandom.h"
27 
28 #include "tcuTestLog.hpp"
29 #include "tcuPixelFormat.hpp"
30 #include "tcuRGBA.hpp"
31 #include "tcuSurface.hpp"
32 #include "tcuVector.hpp"
33 #include "tcuTestLog.hpp"
34 #include "tcuRenderTarget.hpp"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuImageCompare.hpp"
37 
38 #include "gluPixelTransfer.hpp"
39 #include "gluCallLogWrapper.hpp"
40 
41 #include "sglrContext.hpp"
42 #include "sglrReferenceContext.hpp"
43 #include "sglrGLContext.hpp"
44 
45 #include "deMath.h"
46 #include "deStringUtil.hpp"
47 
48 #include <cstring>
49 #include <cmath>
50 #include <vector>
51 #include <sstream>
52 #include <limits>
53 #include <algorithm>
54 
55 #include "glwDefs.hpp"
56 #include "glwEnums.hpp"
57 
58 namespace deqp
59 {
60 namespace gls
61 {
62 
63 using tcu::TestLog;
64 using namespace glw; // GL types
65 
targetToString(Target target)66 std::string Array::targetToString(Target target)
67 {
68 	DE_ASSERT(target < TARGET_LAST);
69 
70 	static const char* targets[] =
71 	{
72 		"element_array",	// TARGET_ELEMENT_ARRAY = 0,
73 		"array"				// TARGET_ARRAY,
74 	};
75 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(targets) == Array::TARGET_LAST);
76 
77 	return targets[(int)target];
78 }
79 
inputTypeToString(InputType type)80 std::string Array::inputTypeToString(InputType type)
81 {
82 	DE_ASSERT(type < INPUTTYPE_LAST);
83 
84 	static const char* types[] =
85 	{
86 		"float",			// INPUTTYPE_FLOAT = 0,
87 		"fixed",			// INPUTTYPE_FIXED,
88 		"double",			// INPUTTYPE_DOUBLE
89 
90 		"byte",				// INPUTTYPE_BYTE,
91 		"short",			// INPUTTYPE_SHORT,
92 
93 		"unsigned_byte",	// INPUTTYPE_UNSIGNED_BYTE,
94 		"unsigned_short",	// INPUTTYPE_UNSIGNED_SHORT,
95 
96 		"int",						// INPUTTYPE_INT,
97 		"unsigned_int",				// INPUTTYPE_UNSIGNED_INT,
98 		"half",						// INPUTTYPE_HALF,
99 		"usigned_int2_10_10_10",	// INPUTTYPE_UNSIGNED_INT_2_10_10_10,
100 		"int2_10_10_10"				// INPUTTYPE_INT_2_10_10_10,
101 	};
102 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::INPUTTYPE_LAST);
103 
104 	return types[(int)type];
105 }
106 
outputTypeToString(OutputType type)107 std::string Array::outputTypeToString(OutputType type)
108 {
109 	DE_ASSERT(type < OUTPUTTYPE_LAST);
110 
111 	static const char* types[] =
112 	{
113 		"float",		// OUTPUTTYPE_FLOAT = 0,
114 		"vec2",			// OUTPUTTYPE_VEC2,
115 		"vec3",			// OUTPUTTYPE_VEC3,
116 		"vec4",			// OUTPUTTYPE_VEC4,
117 
118 		"int",			// OUTPUTTYPE_INT,
119 		"uint",			// OUTPUTTYPE_UINT,
120 
121 		"ivec2",		// OUTPUTTYPE_IVEC2,
122 		"ivec3",		// OUTPUTTYPE_IVEC3,
123 		"ivec4",		// OUTPUTTYPE_IVEC4,
124 
125 		"uvec2",		// OUTPUTTYPE_UVEC2,
126 		"uvec3",		// OUTPUTTYPE_UVEC3,
127 		"uvec4",		// OUTPUTTYPE_UVEC4,
128 	};
129 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::OUTPUTTYPE_LAST);
130 
131 	return types[(int)type];
132 }
133 
usageTypeToString(Usage usage)134 std::string Array::usageTypeToString(Usage usage)
135 {
136 	DE_ASSERT(usage < USAGE_LAST);
137 
138 	static const char* usages[] =
139 	{
140 		"dynamic_draw",	// USAGE_DYNAMIC_DRAW = 0,
141 		"static_draw",	// USAGE_STATIC_DRAW,
142 		"stream_draw",	// USAGE_STREAM_DRAW,
143 
144 		"stream_read",	// USAGE_STREAM_READ,
145 		"stream_copy",	// USAGE_STREAM_COPY,
146 
147 		"static_read",	// USAGE_STATIC_READ,
148 		"static_copy",	// USAGE_STATIC_COPY,
149 
150 		"dynamic_read",	// USAGE_DYNAMIC_READ,
151 		"dynamic_copy",	// USAGE_DYNAMIC_COPY,
152 	};
153 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(usages) == Array::USAGE_LAST);
154 
155 	return usages[(int)usage];
156 }
157 
storageToString(Storage storage)158 std::string	Array::storageToString (Storage storage)
159 {
160 	DE_ASSERT(storage < STORAGE_LAST);
161 
162 	static const char* storages[] =
163 	{
164 		"user_ptr",	// STORAGE_USER = 0,
165 		"buffer"	// STORAGE_BUFFER,
166 	};
167 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(storages) == Array::STORAGE_LAST);
168 
169 	return storages[(int)storage];
170 }
171 
primitiveToString(Primitive primitive)172 std::string Array::primitiveToString (Primitive primitive)
173 {
174 	DE_ASSERT(primitive < PRIMITIVE_LAST);
175 
176 	static const char* primitives[] =
177 	{
178 		"points",			// PRIMITIVE_POINTS ,
179 		"triangles",		// PRIMITIVE_TRIANGLES,
180 		"triangle_fan",		// PRIMITIVE_TRIANGLE_FAN,
181 		"triangle_strip"	// PRIMITIVE_TRIANGLE_STRIP,
182 	};
183 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitives) == Array::PRIMITIVE_LAST);
184 
185 	return primitives[(int)primitive];
186 }
187 
inputTypeSize(InputType type)188 int Array::inputTypeSize (InputType type)
189 {
190 	DE_ASSERT(type < INPUTTYPE_LAST);
191 
192 	static const int size[] =
193 	{
194 		sizeof(float),		// INPUTTYPE_FLOAT = 0,
195 		sizeof(deInt32),	// INPUTTYPE_FIXED,
196 		sizeof(double),		// INPUTTYPE_DOUBLE
197 
198 		sizeof(deInt8),		// INPUTTYPE_BYTE,
199 		sizeof(deInt16),	// INPUTTYPE_SHORT,
200 
201 		sizeof(deUint8),	// INPUTTYPE_UNSIGNED_BYTE,
202 		sizeof(deUint16),	// INPUTTYPE_UNSIGNED_SHORT,
203 
204 		sizeof(deInt32),		// INPUTTYPE_INT,
205 		sizeof(deUint32),		// INPUTTYPE_UNSIGNED_INT,
206 		sizeof(deFloat16),		// INPUTTYPE_HALF,
207 		sizeof(deUint32) / 4,		// INPUTTYPE_UNSIGNED_INT_2_10_10_10,
208 		sizeof(deUint32) / 4		// INPUTTYPE_INT_2_10_10_10,
209 	};
210 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(size) == Array::INPUTTYPE_LAST);
211 
212 	return size[(int)type];
213 }
214 
inputTypeIsFloatType(Array::InputType type)215 static bool inputTypeIsFloatType (Array::InputType type)
216 {
217 	if (type == Array::INPUTTYPE_FLOAT)
218 		return true;
219 	if (type == Array::INPUTTYPE_FIXED)
220 		return true;
221 	if (type == Array::INPUTTYPE_DOUBLE)
222 		return true;
223 	if (type == Array::INPUTTYPE_HALF)
224 		return true;
225 	return false;
226 }
227 
outputTypeIsFloatType(Array::OutputType type)228 static bool outputTypeIsFloatType (Array::OutputType type)
229 {
230 	if (type == Array::OUTPUTTYPE_FLOAT
231 		|| type == Array::OUTPUTTYPE_VEC2
232 		|| type == Array::OUTPUTTYPE_VEC3
233 		|| type == Array::OUTPUTTYPE_VEC4)
234 		return true;
235 
236 	return false;
237 }
238 
239 template<class T>
240 inline T getRandom (deRandom& rnd, T min, T max);
241 
242 template<>
getRandom(deRandom & rnd,GLValue::Float min,GLValue::Float max)243 inline GLValue::Float getRandom (deRandom& rnd, GLValue::Float min, GLValue::Float max)
244 {
245 	if (max < min)
246 		return min;
247 
248 	return GLValue::Float::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
249 }
250 
251 template<>
getRandom(deRandom & rnd,GLValue::Short min,GLValue::Short max)252 inline GLValue::Short getRandom (deRandom& rnd, GLValue::Short min, GLValue::Short max)
253 {
254 	if (max < min)
255 		return min;
256 
257 	return GLValue::Short::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>()))));
258 }
259 
260 template<>
getRandom(deRandom & rnd,GLValue::Ushort min,GLValue::Ushort max)261 inline GLValue::Ushort getRandom (deRandom& rnd, GLValue::Ushort min, GLValue::Ushort max)
262 {
263 	if (max < min)
264 		return min;
265 
266 	return GLValue::Ushort::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>()))));
267 }
268 
269 template<>
getRandom(deRandom & rnd,GLValue::Byte min,GLValue::Byte max)270 inline GLValue::Byte getRandom (deRandom& rnd, GLValue::Byte min, GLValue::Byte max)
271 {
272 	if (max < min)
273 		return min;
274 
275 	return GLValue::Byte::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>()))));
276 }
277 
278 template<>
getRandom(deRandom & rnd,GLValue::Ubyte min,GLValue::Ubyte max)279 inline GLValue::Ubyte getRandom (deRandom& rnd, GLValue::Ubyte min, GLValue::Ubyte max)
280 {
281 	if (max < min)
282 		return min;
283 
284 	return GLValue::Ubyte::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>()))));
285 }
286 
287 template<>
getRandom(deRandom & rnd,GLValue::Fixed min,GLValue::Fixed max)288 inline GLValue::Fixed getRandom (deRandom& rnd, GLValue::Fixed min, GLValue::Fixed max)
289 {
290 	if (max < min)
291 		return min;
292 
293 	return GLValue::Fixed::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
294 }
295 
296 template<>
getRandom(deRandom & rnd,GLValue::Half min,GLValue::Half max)297 inline GLValue::Half getRandom (deRandom& rnd, GLValue::Half min, GLValue::Half max)
298 {
299 	if (max < min)
300 		return min;
301 
302 	float fMax = max.to<float>();
303 	float fMin = min.to<float>();
304 	GLValue::Half h = GLValue::Half::create(fMin + deRandom_getFloat(&rnd) * (fMax - fMin));
305 	return h;
306 }
307 
308 template<>
getRandom(deRandom & rnd,GLValue::Int min,GLValue::Int max)309 inline GLValue::Int getRandom (deRandom& rnd, GLValue::Int min, GLValue::Int max)
310 {
311 	if (max < min)
312 		return min;
313 
314 	return GLValue::Int::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
315 }
316 
317 template<>
getRandom(deRandom & rnd,GLValue::Uint min,GLValue::Uint max)318 inline GLValue::Uint getRandom (deRandom& rnd, GLValue::Uint min, GLValue::Uint max)
319 {
320 	if (max < min)
321 		return min;
322 
323 	return GLValue::Uint::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
324 }
325 
326 template<>
getRandom(deRandom & rnd,GLValue::Double min,GLValue::Double max)327 inline GLValue::Double getRandom (deRandom& rnd, GLValue::Double min, GLValue::Double max)
328 {
329 	if (max < min)
330 		return min;
331 
332 	return GLValue::Double::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
333 }
334 
335 // Minimum difference required between coordinates
336 template<class T>
337 inline T minValue (void);
338 
339 template<>
minValue(void)340 inline GLValue::Float minValue (void)
341 {
342 	return GLValue::Float::create(4 * 1.0f);
343 }
344 
345 template<>
minValue(void)346 inline GLValue::Short minValue (void)
347 {
348 	return GLValue::Short::create(4 * 256);
349 }
350 
351 template<>
minValue(void)352 inline GLValue::Ushort minValue (void)
353 {
354 	return GLValue::Ushort::create(4 * 256);
355 }
356 
357 template<>
minValue(void)358 inline GLValue::Byte minValue (void)
359 {
360 	return GLValue::Byte::create(4 * 1);
361 }
362 
363 template<>
minValue(void)364 inline GLValue::Ubyte minValue (void)
365 {
366 	return GLValue::Ubyte::create(4 * 2);
367 }
368 
369 template<>
minValue(void)370 inline GLValue::Fixed minValue (void)
371 {
372 	return GLValue::Fixed::create(4 * 512);
373 }
374 
375 template<>
minValue(void)376 inline GLValue::Int minValue (void)
377 {
378 	return GLValue::Int::create(4 * 16777216);
379 }
380 
381 template<>
minValue(void)382 inline GLValue::Uint minValue (void)
383 {
384 	return GLValue::Uint::create(4 * 16777216);
385 }
386 
387 template<>
minValue(void)388 inline GLValue::Half minValue (void)
389 {
390 	return GLValue::Half::create(4 * 1.0f);
391 }
392 
393 template<>
minValue(void)394 inline GLValue::Double minValue (void)
395 {
396 	return GLValue::Double::create(4 * 1.0f);
397 }
398 
399 template<class T>
400 inline T abs (T val);
401 
402 template<>
abs(GLValue::Fixed val)403 inline GLValue::Fixed abs (GLValue::Fixed val)
404 {
405 	return GLValue::Fixed::create(0x7FFFu & val.getValue());
406 }
407 
408 template<>
abs(GLValue::Ubyte val)409 inline GLValue::Ubyte abs (GLValue::Ubyte val)
410 {
411 	return val;
412 }
413 
414 template<>
abs(GLValue::Byte val)415 inline GLValue::Byte abs (GLValue::Byte val)
416 {
417 	return GLValue::Byte::create(0x7Fu & val.getValue());
418 }
419 
420 template<>
abs(GLValue::Ushort val)421 inline GLValue::Ushort abs (GLValue::Ushort val)
422 {
423 	return val;
424 }
425 
426 template<>
abs(GLValue::Short val)427 inline GLValue::Short abs (GLValue::Short val)
428 {
429 	return GLValue::Short::create(0x7FFFu & val.getValue());
430 }
431 
432 template<>
abs(GLValue::Float val)433 inline GLValue::Float abs (GLValue::Float val)
434 {
435 	return GLValue::Float::create(std::fabs(val.to<float>()));
436 }
437 
438 template<>
abs(GLValue::Uint val)439 inline GLValue::Uint abs (GLValue::Uint val)
440 {
441 	return val;
442 }
443 
444 template<>
abs(GLValue::Int val)445 inline GLValue::Int abs (GLValue::Int val)
446 {
447 	return GLValue::Int::create(0x7FFFFFFFu & val.getValue());
448 }
449 
450 template<>
abs(GLValue::Half val)451 inline GLValue::Half abs (GLValue::Half val)
452 {
453 	return GLValue::Half::create(std::fabs(val.to<float>()));
454 }
455 
456 template<>
abs(GLValue::Double val)457 inline GLValue::Double abs (GLValue::Double val)
458 {
459 	return GLValue::Double::create(std::fabs(val.to<float>()));
460 }
461 
462 template<class T>
alignmentSafeAssignment(char * dst,T val)463 inline static void alignmentSafeAssignment (char* dst, T val)
464 {
465 	std::memcpy(dst, &val, sizeof(T));
466 }
467 
ContextArray(Storage storage,sglr::Context & context)468 ContextArray::ContextArray (Storage storage, sglr::Context& context)
469 	: m_storage			(storage)
470 	, m_ctx				(context)
471 	, m_glBuffer		(0)
472 	, m_bound			(false)
473 	, m_attribNdx		(0)
474 	, m_size			(0)
475 	, m_data			(DE_NULL)
476 	, m_componentCount	(1)
477 	, m_target			(Array::TARGET_ARRAY)
478 	, m_inputType		(Array::INPUTTYPE_FLOAT)
479 	, m_outputType		(Array::OUTPUTTYPE_VEC4)
480 	, m_normalize		(false)
481 	, m_stride			(0)
482 	, m_offset			(0)
483 {
484 	if (m_storage == STORAGE_BUFFER)
485 	{
486 		m_ctx.genBuffers(1, &m_glBuffer);
487 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glGenBuffers()");
488 	}
489 }
490 
~ContextArray(void)491 ContextArray::~ContextArray	(void)
492 {
493 	if (m_storage == STORAGE_BUFFER)
494 	{
495 		m_ctx.deleteBuffers(1, &m_glBuffer);
496 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDeleteBuffers()");
497 	}
498 	else if (m_storage == STORAGE_USER)
499 		delete[] m_data;
500 	else
501 		DE_ASSERT(false);
502 }
503 
getArray(int i)504 Array* ContextArrayPack::getArray (int i)
505 {
506 	return m_arrays.at(i);
507 }
508 
data(Target target,int size,const char * ptr,Usage usage)509 void ContextArray::data (Target target, int size, const char* ptr, Usage usage)
510 {
511 	m_size = size;
512 	m_target = target;
513 
514 	if (m_storage == STORAGE_BUFFER)
515 	{
516 		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
517 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
518 
519 		m_ctx.bufferData(targetToGL(target), size, ptr, usageToGL(usage));
520 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferData()");
521 	}
522 	else if (m_storage == STORAGE_USER)
523 	{
524 		if (m_data)
525 			delete[] m_data;
526 
527 		m_data = new char[size];
528 		std::memcpy(m_data, ptr, size);
529 	}
530 	else
531 		DE_ASSERT(false);
532 }
533 
subdata(Target target,int offset,int size,const char * ptr)534 void ContextArray::subdata (Target target, int offset, int size, const char* ptr)
535 {
536 	m_target = target;
537 
538 	if (m_storage == STORAGE_BUFFER)
539 	{
540 		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
541 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
542 
543 		m_ctx.bufferSubData(targetToGL(target), offset, size, ptr);
544 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferSubData()");
545 	}
546 	else if (m_storage == STORAGE_USER)
547 		std::memcpy(m_data + offset, ptr, size);
548 	else
549 		DE_ASSERT(false);
550 }
551 
bind(int attribNdx,int offset,int size,InputType inputType,OutputType outType,bool normalized,int stride)552 void ContextArray::bind (int attribNdx, int offset, int size, InputType inputType, OutputType outType, bool normalized, int stride)
553 {
554 	m_attribNdx			= attribNdx;
555 	m_bound				= true;
556 	m_componentCount	= size;
557 	m_inputType			= inputType;
558 	m_outputType		= outType;
559 	m_normalize			= normalized;
560 	m_stride			= stride;
561 	m_offset			= offset;
562 }
563 
bindIndexArray(Array::Target target)564 void ContextArray::bindIndexArray (Array::Target target)
565 {
566 	if (m_storage == STORAGE_USER)
567 	{
568 	}
569 	else if (m_storage == STORAGE_BUFFER)
570 	{
571 		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
572 	}
573 }
574 
glBind(deUint32 loc)575 void ContextArray::glBind (deUint32 loc)
576 {
577 	if (m_storage == STORAGE_BUFFER)
578 	{
579 		m_ctx.bindBuffer(targetToGL(m_target), m_glBuffer);
580 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
581 
582 		if (!inputTypeIsFloatType(m_inputType))
583 		{
584 			// Input is not float type
585 
586 			if (outputTypeIsFloatType(m_outputType))
587 			{
588 				// Output type is float type
589 				m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, (GLvoid*)((GLintptr)m_offset));
590 				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
591 			}
592 			else
593 			{
594 				// Output type is int type
595 				m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, (GLvoid*)((GLintptr)m_offset));
596 				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()");
597 			}
598 		}
599 		else
600 		{
601 			// Input type is float type
602 
603 			// Output type must be float type
604 			DE_ASSERT(m_outputType == OUTPUTTYPE_FLOAT || m_outputType == OUTPUTTYPE_VEC2 || m_outputType == OUTPUTTYPE_VEC3 || m_outputType == OUTPUTTYPE_VEC4);
605 
606 			m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, (GLvoid*)((GLintptr)m_offset));
607 			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
608 		}
609 
610 		m_ctx.bindBuffer(targetToGL(m_target), 0);
611 	}
612 	else if (m_storage == STORAGE_USER)
613 	{
614 		m_ctx.bindBuffer(targetToGL(m_target), 0);
615 		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
616 
617 		if (!inputTypeIsFloatType(m_inputType))
618 		{
619 			// Input is not float type
620 
621 			if (outputTypeIsFloatType(m_outputType))
622 			{
623 				// Output type is float type
624 				m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, m_data + m_offset);
625 				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
626 			}
627 			else
628 			{
629 				// Output type is int type
630 				m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, m_data + m_offset);
631 				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()");
632 			}
633 		}
634 		else
635 		{
636 			// Input type is float type
637 
638 			// Output type must be float type
639 			DE_ASSERT(m_outputType == OUTPUTTYPE_FLOAT || m_outputType == OUTPUTTYPE_VEC2 || m_outputType == OUTPUTTYPE_VEC3 || m_outputType == OUTPUTTYPE_VEC4);
640 
641 			m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, m_data + m_offset);
642 			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
643 		}
644 	}
645 	else
646 		DE_ASSERT(false);
647 }
648 
targetToGL(Array::Target target)649 GLenum ContextArray::targetToGL (Array::Target target)
650 {
651 	DE_ASSERT(target < TARGET_LAST);
652 
653 	static const GLenum targets[] =
654 	{
655 		GL_ELEMENT_ARRAY_BUFFER,	// TARGET_ELEMENT_ARRAY = 0,
656 		GL_ARRAY_BUFFER				// TARGET_ARRAY,
657 	};
658 
659 	return targets[(int)target];
660 }
661 
usageToGL(Array::Usage usage)662 GLenum ContextArray::usageToGL (Array::Usage usage)
663 {
664 	DE_ASSERT(usage < USAGE_LAST);
665 
666 	static const GLenum usages[] =
667 	{
668 		GL_DYNAMIC_DRAW,	// USAGE_DYNAMIC_DRAW = 0,
669 		GL_STATIC_DRAW,		// USAGE_STATIC_DRAW,
670 		GL_STREAM_DRAW,		// USAGE_STREAM_DRAW,
671 
672 		GL_STREAM_READ,		// USAGE_STREAM_READ,
673 		GL_STREAM_COPY,		// USAGE_STREAM_COPY,
674 
675 		GL_STATIC_READ,		// USAGE_STATIC_READ,
676 		GL_STATIC_COPY,		// USAGE_STATIC_COPY,
677 
678 		GL_DYNAMIC_READ,	// USAGE_DYNAMIC_READ,
679 		GL_DYNAMIC_COPY		// USAGE_DYNAMIC_COPY,
680 	};
681 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(usages) == Array::USAGE_LAST);
682 
683 	return usages[(int)usage];
684 }
685 
inputTypeToGL(Array::InputType type)686 GLenum ContextArray::inputTypeToGL (Array::InputType type)
687 {
688 	DE_ASSERT(type < INPUTTYPE_LAST);
689 
690 	static const GLenum types[] =
691 	{
692 		GL_FLOAT,				// INPUTTYPE_FLOAT = 0,
693 		GL_FIXED,				// INPUTTYPE_FIXED,
694 		GL_DOUBLE,				// INPUTTYPE_DOUBLE
695 		GL_BYTE,				// INPUTTYPE_BYTE,
696 		GL_SHORT,				// INPUTTYPE_SHORT,
697 		GL_UNSIGNED_BYTE,		// INPUTTYPE_UNSIGNED_BYTE,
698 		GL_UNSIGNED_SHORT,		// INPUTTYPE_UNSIGNED_SHORT,
699 
700 		GL_INT,					// INPUTTYPE_INT,
701 		GL_UNSIGNED_INT,		// INPUTTYPE_UNSIGNED_INT,
702 		GL_HALF_FLOAT,			// INPUTTYPE_HALF,
703 		GL_UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
704 		GL_INT_2_10_10_10_REV			// INPUTTYPE_INT_2_10_10_10,
705 	};
706 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::INPUTTYPE_LAST);
707 
708 	return types[(int)type];
709 }
710 
outputTypeToGLType(Array::OutputType type)711 std::string ContextArray::outputTypeToGLType (Array::OutputType type)
712 {
713 	DE_ASSERT(type < OUTPUTTYPE_LAST);
714 
715 	static const char* types[] =
716 	{
717 		"float",		// OUTPUTTYPE_FLOAT = 0,
718 		"vec2",			// OUTPUTTYPE_VEC2,
719 		"vec3",			// OUTPUTTYPE_VEC3,
720 		"vec4",			// OUTPUTTYPE_VEC4,
721 
722 		"int",			// OUTPUTTYPE_INT,
723 		"uint",			// OUTPUTTYPE_UINT,
724 
725 		"ivec2",		// OUTPUTTYPE_IVEC2,
726 		"ivec3",		// OUTPUTTYPE_IVEC3,
727 		"ivec4",		// OUTPUTTYPE_IVEC4,
728 
729 		"uvec2",		// OUTPUTTYPE_UVEC2,
730 		"uvec3",		// OUTPUTTYPE_UVEC3,
731 		"uvec4",		// OUTPUTTYPE_UVEC4,
732 	};
733 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(types) == Array::OUTPUTTYPE_LAST);
734 
735 	return types[type];
736 }
737 
primitiveToGL(Array::Primitive primitive)738 GLenum ContextArray::primitiveToGL (Array::Primitive primitive)
739 {
740 	GLenum primitives[] =
741 	{
742 		GL_POINTS,			// PRIMITIVE_POINTS = 0,
743 		GL_TRIANGLES,		// PRIMITIVE_TRIANGLES,
744 		GL_TRIANGLE_FAN,	// PRIMITIVE_TRIANGLE_FAN,
745 		GL_TRIANGLE_STRIP	// PRIMITIVE_TRIANGLE_STRIP,
746 	};
747 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitives) == Array::PRIMITIVE_LAST);
748 
749 	return primitives[(int)primitive];
750 }
751 
ContextArrayPack(glu::RenderContext & renderCtx,sglr::Context & drawContext)752 ContextArrayPack::ContextArrayPack (glu::RenderContext& renderCtx, sglr::Context& drawContext)
753 	: m_renderCtx	(renderCtx)
754 	, m_ctx			(drawContext)
755 	, m_program		(DE_NULL)
756 	, m_screen		(std::min(512, renderCtx.getRenderTarget().getWidth()), std::min(512, renderCtx.getRenderTarget().getHeight()))
757 {
758 }
759 
~ContextArrayPack(void)760 ContextArrayPack::~ContextArrayPack (void)
761 {
762 	for (std::vector<ContextArray*>::iterator itr = m_arrays.begin(); itr != m_arrays.end(); itr++)
763 		delete *itr;
764 
765 	delete m_program;
766 }
767 
getArrayCount(void)768 int ContextArrayPack::getArrayCount (void)
769 {
770 	return (int)m_arrays.size();
771 }
772 
newArray(Array::Storage storage)773 void ContextArrayPack::newArray (Array::Storage storage)
774 {
775 	m_arrays.push_back(new ContextArray(storage, m_ctx));
776 }
777 
778 class ContextShaderProgram : public sglr::ShaderProgram
779 {
780 public:
781 												ContextShaderProgram		(const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays);
782 
783 	void										shadeVertices				(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
784 	void										shadeFragments				(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
785 
786 private:
787 	static std::string							genVertexSource				(const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays);
788 	static std::string							genFragmentSource			(const glu::RenderContext& ctx);
789 	static rr::GenericVecType					mapOutputType				(const Array::OutputType& type);
790 	static int									getComponentCount			(const Array::OutputType& type);
791 
792 	static sglr::pdec::ShaderProgramDeclaration createProgramDeclaration	(const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays);
793 
794 	std::vector<int>							m_componentCount;
795 	std::vector<rr::GenericVecType>				m_attrType;
796 };
797 
ContextShaderProgram(const glu::RenderContext & ctx,const std::vector<ContextArray * > & arrays)798 ContextShaderProgram::ContextShaderProgram (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays)
799 	: sglr::ShaderProgram	(createProgramDeclaration(ctx, arrays))
800 	, m_componentCount		(arrays.size())
801 	, m_attrType			(arrays.size())
802 {
803 	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
804 	{
805 		m_componentCount[arrayNdx]	= getComponentCount(arrays[arrayNdx]->getOutputType());
806 		m_attrType[arrayNdx]		= mapOutputType(arrays[arrayNdx]->getOutputType());
807 	}
808 }
809 
810 template <typename T>
calcShaderColorCoord(tcu::Vec2 & coord,tcu::Vec3 & color,const tcu::Vector<T,4> & attribValue,bool isCoordinate,int numComponents)811 void calcShaderColorCoord (tcu::Vec2& coord, tcu::Vec3& color, const tcu::Vector<T, 4>& attribValue, bool isCoordinate, int numComponents)
812 {
813 	if (isCoordinate)
814 		switch (numComponents)
815 		{
816 			case 1:	coord = tcu::Vec2((float)attribValue.x(),					(float)attribValue.x());					break;
817 			case 2:	coord = tcu::Vec2((float)attribValue.x(),					(float)attribValue.y());					break;
818 			case 3:	coord = tcu::Vec2((float)attribValue.x() + attribValue.z(),	(float)attribValue.y());					break;
819 			case 4:	coord = tcu::Vec2((float)attribValue.x() + attribValue.z(),	(float)attribValue.y() + attribValue.w());	break;
820 
821 			default:
822 				DE_ASSERT(false);
823 		}
824 	else
825 	{
826 		switch (numComponents)
827 		{
828 			case 1:
829 				color = color * (float)attribValue.x();
830 				break;
831 
832 			case 2:
833 				color.x() = color.x() * attribValue.x();
834 				color.y() = color.y() * attribValue.y();
835 				break;
836 
837 			case 3:
838 				color.x() = color.x() * attribValue.x();
839 				color.y() = color.y() * attribValue.y();
840 				color.z() = color.z() * attribValue.z();
841 				break;
842 
843 			case 4:
844 				color.x() = color.x() * attribValue.x() * attribValue.w();
845 				color.y() = color.y() * attribValue.y() * attribValue.w();
846 				color.z() = color.z() * attribValue.z() * attribValue.w();
847 				break;
848 
849 			default:
850 				DE_ASSERT(false);
851 		}
852 	}
853 }
854 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const855 void ContextShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
856 {
857 	const float	u_coordScale = getUniformByName("u_coordScale").value.f;
858 	const float u_colorScale = getUniformByName("u_colorScale").value.f;
859 
860 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
861 	{
862 		const size_t varyingLocColor = 0;
863 
864 		rr::VertexPacket& packet = *packets[packetNdx];
865 
866 		// Calc output color
867 		tcu::Vec2 coord = tcu::Vec2(1.0, 1.0);
868 		tcu::Vec3 color = tcu::Vec3(1.0, 1.0, 1.0);
869 
870 		for (int attribNdx = 0; attribNdx < (int)m_attrType.size(); attribNdx++)
871 		{
872 			const int numComponents = m_componentCount[attribNdx];
873 
874 			switch (m_attrType[attribNdx])
875 			{
876 				case rr::GENERICVECTYPE_FLOAT:	calcShaderColorCoord(coord, color, rr::readVertexAttribFloat(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents);	break;
877 				case rr::GENERICVECTYPE_INT32:	calcShaderColorCoord(coord, color, rr::readVertexAttribInt	(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents);	break;
878 				case rr::GENERICVECTYPE_UINT32:	calcShaderColorCoord(coord, color, rr::readVertexAttribUint	(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents);	break;
879 				default:
880 					DE_ASSERT(false);
881 			}
882 		}
883 
884 		// Transform position
885 		{
886 			packet.position = tcu::Vec4(u_coordScale * coord.x(), u_coordScale * coord.y(), 1.0f, 1.0f);
887 		}
888 
889 		// Pass color to FS
890 		{
891 			packet.outputs[varyingLocColor] = tcu::Vec4(u_colorScale * color.x(), u_colorScale * color.y(), u_colorScale * color.z(), 1.0f);
892 		}
893 	}
894 }
895 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const896 void ContextShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
897 {
898 	const size_t varyingLocColor = 0;
899 
900 	// Triangles are flashaded
901 	tcu::Vec4 color = rr::readTriangleVarying<float>(packets[0], context, varyingLocColor, 0);
902 
903 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
904 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
905 			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
906 }
907 
genVertexSource(const glu::RenderContext & ctx,const std::vector<ContextArray * > & arrays)908 std::string ContextShaderProgram::genVertexSource (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays)
909 {
910 	std::stringstream vertexShaderTmpl;
911 	std::map<std::string, std::string> params;
912 
913 	if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_300_ES))
914 	{
915 		params["VTX_IN"]		= "in";
916 		params["VTX_OUT"]		= "out";
917 		params["FRAG_IN"]		= "in";
918 		params["FRAG_COLOR"]	= "dEQP_FragColor";
919 		params["VTX_HDR"]		= "#version 300 es\n";
920 		params["FRAG_HDR"]		= "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
921 	}
922 	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_100_ES))
923 	{
924 		params["VTX_IN"]		= "attribute";
925 		params["VTX_OUT"]		= "varying";
926 		params["FRAG_IN"]		= "varying";
927 		params["FRAG_COLOR"]	= "gl_FragColor";
928 		params["VTX_HDR"]		= "";
929 		params["FRAG_HDR"]		= "";
930 	}
931 	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_330))
932 	{
933 		params["VTX_IN"]		= "in";
934 		params["VTX_OUT"]		= "out";
935 		params["FRAG_IN"]		= "in";
936 		params["FRAG_COLOR"]	= "dEQP_FragColor";
937 		params["VTX_HDR"]		= "#version 330\n";
938 		params["FRAG_HDR"]		= "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
939 	}
940 	else
941 		DE_ASSERT(DE_FALSE);
942 
943 	vertexShaderTmpl << "${VTX_HDR}";
944 
945 	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
946 	{
947 		vertexShaderTmpl
948 			<< "${VTX_IN} highp " <<  ContextArray::outputTypeToGLType(arrays[arrayNdx]->getOutputType()) << " a_" << arrays[arrayNdx]->getAttribNdx() << ";\n";
949 	}
950 
951 	vertexShaderTmpl <<
952 		"uniform highp float u_coordScale;\n"
953 		"uniform highp float u_colorScale;\n"
954 		"${VTX_OUT} mediump vec4 v_color;\n"
955 		"void main(void)\n"
956 		"{\n"
957 		"\tgl_PointSize = 1.0;\n"
958 		"\thighp vec2 coord = vec2(1.0, 1.0);\n"
959 		"\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n";
960 
961 	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
962 	{
963 		if (arrays[arrayNdx]->getAttribNdx() == 0)
964 		{
965 			switch (arrays[arrayNdx]->getOutputType())
966 			{
967 				case (Array::OUTPUTTYPE_FLOAT):
968 					vertexShaderTmpl <<
969 						"\tcoord = vec2(a_0);\n";
970 					break;
971 
972 				case (Array::OUTPUTTYPE_VEC2):
973 					vertexShaderTmpl <<
974 						"\tcoord = a_0.xy;\n";
975 					break;
976 
977 				case (Array::OUTPUTTYPE_VEC3):
978 					vertexShaderTmpl <<
979 						"\tcoord = a_0.xy;\n"
980 						"\tcoord.x = coord.x + a_0.z;\n";
981 					break;
982 
983 				case (Array::OUTPUTTYPE_VEC4):
984 					vertexShaderTmpl <<
985 						"\tcoord = a_0.xy;\n"
986 						"\tcoord += a_0.zw;\n";
987 					break;
988 
989 				case (Array::OUTPUTTYPE_IVEC2):
990 				case (Array::OUTPUTTYPE_UVEC2):
991 					vertexShaderTmpl <<
992 						"\tcoord = vec2(a_0.xy);\n";
993 					break;
994 
995 				case (Array::OUTPUTTYPE_IVEC3):
996 				case (Array::OUTPUTTYPE_UVEC3):
997 					vertexShaderTmpl <<
998 						"\tcoord = vec2(a_0.xy);\n"
999 						"\tcoord.x = coord.x + float(a_0.z);\n";
1000 					break;
1001 
1002 				case (Array::OUTPUTTYPE_IVEC4):
1003 				case (Array::OUTPUTTYPE_UVEC4):
1004 					vertexShaderTmpl <<
1005 						"\tcoord = vec2(a_0.xy);\n"
1006 						"\tcoord += vec2(a_0.zw);\n";
1007 					break;
1008 
1009 				default:
1010 					DE_ASSERT(false);
1011 					break;
1012 			}
1013 			continue;
1014 		}
1015 
1016 		switch (arrays[arrayNdx]->getOutputType())
1017 		{
1018 			case (Array::OUTPUTTYPE_FLOAT):
1019 				vertexShaderTmpl <<
1020 					"\tcolor = color * a_" << arrays[arrayNdx]->getAttribNdx() << ";\n";
1021 				break;
1022 
1023 			case (Array::OUTPUTTYPE_VEC2):
1024 				vertexShaderTmpl <<
1025 					"\tcolor.rg = color.rg * a_" << arrays[arrayNdx]->getAttribNdx() << ".xy;\n";
1026 				break;
1027 
1028 			case (Array::OUTPUTTYPE_VEC3):
1029 				vertexShaderTmpl <<
1030 					"\tcolor = color.rgb * a_" << arrays[arrayNdx]->getAttribNdx() << ".xyz;\n";
1031 				break;
1032 
1033 			case (Array::OUTPUTTYPE_VEC4):
1034 				vertexShaderTmpl <<
1035 					"\tcolor = color.rgb * a_" << arrays[arrayNdx]->getAttribNdx() << ".xyz * a_" << arrays[arrayNdx]->getAttribNdx() << ".w;\n";
1036 				break;
1037 
1038 			default:
1039 				DE_ASSERT(false);
1040 				break;
1041 		}
1042 	}
1043 
1044 	vertexShaderTmpl <<
1045 		"\tv_color = vec4(u_colorScale * color, 1.0);\n"
1046 		"\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n"
1047 		"}\n";
1048 
1049 	return tcu::StringTemplate(vertexShaderTmpl.str().c_str()).specialize(params);
1050 }
1051 
genFragmentSource(const glu::RenderContext & ctx)1052 std::string ContextShaderProgram::genFragmentSource (const glu::RenderContext& ctx)
1053 {
1054 	std::map<std::string, std::string> params;
1055 
1056 	if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_300_ES))
1057 	{
1058 		params["VTX_IN"]		= "in";
1059 		params["VTX_OUT"]		= "out";
1060 		params["FRAG_IN"]		= "in";
1061 		params["FRAG_COLOR"]	= "dEQP_FragColor";
1062 		params["VTX_HDR"]		= "#version 300 es\n";
1063 		params["FRAG_HDR"]		= "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1064 	}
1065 	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_100_ES))
1066 	{
1067 		params["VTX_IN"]		= "attribute";
1068 		params["VTX_OUT"]		= "varying";
1069 		params["FRAG_IN"]		= "varying";
1070 		params["FRAG_COLOR"]	= "gl_FragColor";
1071 		params["VTX_HDR"]		= "";
1072 		params["FRAG_HDR"]		= "";
1073 	}
1074 	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_330))
1075 	{
1076 		params["VTX_IN"]		= "in";
1077 		params["VTX_OUT"]		= "out";
1078 		params["FRAG_IN"]		= "in";
1079 		params["FRAG_COLOR"]	= "dEQP_FragColor";
1080 		params["VTX_HDR"]		= "#version 330\n";
1081 		params["FRAG_HDR"]		= "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1082 	}
1083 	else
1084 		DE_ASSERT(DE_FALSE);
1085 
1086 	static const char* fragmentShaderTmpl =
1087 		"${FRAG_HDR}"
1088 		"${FRAG_IN} mediump vec4 v_color;\n"
1089 		"void main(void)\n"
1090 		"{\n"
1091 		"\t${FRAG_COLOR} = v_color;\n"
1092 		"}\n";
1093 
1094 	return tcu::StringTemplate(fragmentShaderTmpl).specialize(params);
1095 }
1096 
mapOutputType(const Array::OutputType & type)1097 rr::GenericVecType ContextShaderProgram::mapOutputType (const Array::OutputType& type)
1098 {
1099 	switch (type)
1100 	{
1101 		case (Array::OUTPUTTYPE_FLOAT):
1102 		case (Array::OUTPUTTYPE_VEC2):
1103 		case (Array::OUTPUTTYPE_VEC3):
1104 		case (Array::OUTPUTTYPE_VEC4):
1105 			return rr::GENERICVECTYPE_FLOAT;
1106 
1107 		case (Array::OUTPUTTYPE_INT):
1108 		case (Array::OUTPUTTYPE_IVEC2):
1109 		case (Array::OUTPUTTYPE_IVEC3):
1110 		case (Array::OUTPUTTYPE_IVEC4):
1111 			return rr::GENERICVECTYPE_INT32;
1112 
1113 		case (Array::OUTPUTTYPE_UINT):
1114 		case (Array::OUTPUTTYPE_UVEC2):
1115 		case (Array::OUTPUTTYPE_UVEC3):
1116 		case (Array::OUTPUTTYPE_UVEC4):
1117 			return rr::GENERICVECTYPE_UINT32;
1118 
1119 		default:
1120 			DE_ASSERT(false);
1121 			return rr::GENERICVECTYPE_LAST;
1122 	}
1123 }
1124 
getComponentCount(const Array::OutputType & type)1125 int ContextShaderProgram::getComponentCount (const Array::OutputType& type)
1126 {
1127 	switch (type)
1128 	{
1129 		case (Array::OUTPUTTYPE_FLOAT):
1130 		case (Array::OUTPUTTYPE_INT):
1131 		case (Array::OUTPUTTYPE_UINT):
1132 			return 1;
1133 
1134 		case (Array::OUTPUTTYPE_VEC2):
1135 		case (Array::OUTPUTTYPE_IVEC2):
1136 		case (Array::OUTPUTTYPE_UVEC2):
1137 			return 2;
1138 
1139 		case (Array::OUTPUTTYPE_VEC3):
1140 		case (Array::OUTPUTTYPE_IVEC3):
1141 		case (Array::OUTPUTTYPE_UVEC3):
1142 			return 3;
1143 
1144 		case (Array::OUTPUTTYPE_VEC4):
1145 		case (Array::OUTPUTTYPE_IVEC4):
1146 		case (Array::OUTPUTTYPE_UVEC4):
1147 			return 4;
1148 
1149 		default:
1150 			DE_ASSERT(false);
1151 			return 0;
1152 	}
1153 }
1154 
createProgramDeclaration(const glu::RenderContext & ctx,const std::vector<ContextArray * > & arrays)1155 sglr::pdec::ShaderProgramDeclaration ContextShaderProgram::createProgramDeclaration (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays)
1156 {
1157 	sglr::pdec::ShaderProgramDeclaration decl;
1158 
1159 	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1160 		decl << sglr::pdec::VertexAttribute(std::string("a_") + de::toString(arrayNdx), mapOutputType(arrays[arrayNdx]->getOutputType()));
1161 
1162 	decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
1163 	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
1164 
1165 	decl << sglr::pdec::VertexSource(genVertexSource(ctx, arrays));
1166 	decl << sglr::pdec::FragmentSource(genFragmentSource(ctx));
1167 
1168 	decl << sglr::pdec::Uniform("u_coordScale", glu::TYPE_FLOAT);
1169 	decl << sglr::pdec::Uniform("u_colorScale", glu::TYPE_FLOAT);
1170 
1171 	return decl;
1172 }
1173 
updateProgram(void)1174 void ContextArrayPack::updateProgram (void)
1175 {
1176 	delete m_program;
1177 	m_program = new ContextShaderProgram(m_renderCtx, m_arrays);
1178 }
1179 
render(Array::Primitive primitive,int firstVertex,int vertexCount,bool useVao,float coordScale,float colorScale)1180 void ContextArrayPack::render (Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, float colorScale)
1181 {
1182 	deUint32 program = 0;
1183 	deUint32 vaoId = 0;
1184 
1185 	updateProgram();
1186 
1187 	m_ctx.viewport(0, 0, m_screen.getWidth(), m_screen.getHeight());
1188 	m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
1189 	m_ctx.clear(GL_COLOR_BUFFER_BIT);
1190 
1191 	program = m_ctx.createProgram(m_program);
1192 
1193 	m_ctx.useProgram(program);
1194 	GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glUseProgram()");
1195 
1196 	m_ctx.uniform1f(m_ctx.getUniformLocation(program, "u_coordScale"), coordScale);
1197 	m_ctx.uniform1f(m_ctx.getUniformLocation(program, "u_colorScale"), colorScale);
1198 
1199 	if (useVao)
1200 	{
1201 		m_ctx.genVertexArrays(1, &vaoId);
1202 		m_ctx.bindVertexArray(vaoId);
1203 	}
1204 
1205 	for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
1206 	{
1207 		if (m_arrays[arrayNdx]->isBound())
1208 		{
1209 			std::stringstream attribName;
1210 			attribName << "a_" << m_arrays[arrayNdx]->getAttribNdx();
1211 
1212 			deUint32 loc = m_ctx.getAttribLocation(program, attribName.str().c_str());
1213 			m_ctx.enableVertexAttribArray(loc);
1214 			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glEnableVertexAttribArray()");
1215 
1216 			m_arrays[arrayNdx]->glBind(loc);
1217 		}
1218 	}
1219 
1220 	DE_ASSERT((firstVertex % 6) == 0);
1221 	m_ctx.drawArrays(ContextArray::primitiveToGL(primitive), firstVertex, vertexCount - firstVertex);
1222 	GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArrays()");
1223 
1224 	for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
1225 	{
1226 		if (m_arrays[arrayNdx]->isBound())
1227 		{
1228 			std::stringstream attribName;
1229 			attribName << "a_" << m_arrays[arrayNdx]->getAttribNdx();
1230 
1231 			deUint32 loc = m_ctx.getAttribLocation(program, attribName.str().c_str());
1232 
1233 			m_ctx.disableVertexAttribArray(loc);
1234 			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDisableVertexAttribArray()");
1235 		}
1236 	}
1237 
1238 	if (useVao)
1239 		m_ctx.deleteVertexArrays(1, &vaoId);
1240 
1241 	m_ctx.deleteProgram(program);
1242 	m_ctx.useProgram(0);
1243 	m_ctx.readPixels(m_screen, 0, 0, m_screen.getWidth(), m_screen.getHeight());
1244 }
1245 
1246 // GLValue
1247 
getMaxValue(Array::InputType type)1248 GLValue GLValue::getMaxValue (Array::InputType type)
1249 {
1250 	GLValue rangesHi[(int)Array::INPUTTYPE_LAST];
1251 
1252 	rangesHi[(int)Array::INPUTTYPE_FLOAT]			= GLValue(Float::create(127.0f));
1253 	rangesHi[(int)Array::INPUTTYPE_DOUBLE]			= GLValue(Double::create(127.0f));
1254 	rangesHi[(int)Array::INPUTTYPE_BYTE]			= GLValue(Byte::create(127));
1255 	rangesHi[(int)Array::INPUTTYPE_UNSIGNED_BYTE]	= GLValue(Ubyte::create(255));
1256 	rangesHi[(int)Array::INPUTTYPE_UNSIGNED_SHORT]	= GLValue(Ushort::create(65530));
1257 	rangesHi[(int)Array::INPUTTYPE_SHORT]			= GLValue(Short::create(32760));
1258 	rangesHi[(int)Array::INPUTTYPE_FIXED]			= GLValue(Fixed::create(32760));
1259 	rangesHi[(int)Array::INPUTTYPE_INT]				= GLValue(Int::create(2147483647));
1260 	rangesHi[(int)Array::INPUTTYPE_UNSIGNED_INT]	= GLValue(Uint::create(4294967295u));
1261 	rangesHi[(int)Array::INPUTTYPE_HALF]			= GLValue(Half::create(256.0f));
1262 
1263 	return rangesHi[(int)type];
1264 }
1265 
getMinValue(Array::InputType type)1266 GLValue GLValue::getMinValue (Array::InputType type)
1267 {
1268 	GLValue rangesLo[(int)Array::INPUTTYPE_LAST];
1269 
1270 	rangesLo[(int)Array::INPUTTYPE_FLOAT]			= GLValue(Float::create(-127.0f));
1271 	rangesLo[(int)Array::INPUTTYPE_DOUBLE]			= GLValue(Double::create(-127.0f));
1272 	rangesLo[(int)Array::INPUTTYPE_BYTE]			= GLValue(Byte::create(-127));
1273 	rangesLo[(int)Array::INPUTTYPE_UNSIGNED_BYTE]	= GLValue(Ubyte::create(0));
1274 	rangesLo[(int)Array::INPUTTYPE_UNSIGNED_SHORT]	= GLValue(Ushort::create(0));
1275 	rangesLo[(int)Array::INPUTTYPE_SHORT]			= GLValue(Short::create(-32760));
1276 	rangesLo[(int)Array::INPUTTYPE_FIXED]			= GLValue(Fixed::create(-32760));
1277 	rangesLo[(int)Array::INPUTTYPE_INT]				= GLValue(Int::create(-2147483647));
1278 	rangesLo[(int)Array::INPUTTYPE_UNSIGNED_INT]	= GLValue(Uint::create(0));
1279 	rangesLo[(int)Array::INPUTTYPE_HALF]			= GLValue(Half::create(-256.0f));
1280 
1281 	return rangesLo[(int)type];
1282 }
1283 
toFloat(void) const1284 float GLValue::toFloat (void) const
1285 {
1286 	switch (type)
1287 	{
1288 		case Array::INPUTTYPE_FLOAT:
1289 			return fl.getValue();
1290 			break;
1291 
1292 		case Array::INPUTTYPE_BYTE:
1293 			return b.getValue();
1294 			break;
1295 
1296 		case Array::INPUTTYPE_UNSIGNED_BYTE:
1297 			return ub.getValue();
1298 			break;
1299 
1300 		case Array::INPUTTYPE_SHORT:
1301 			return s.getValue();
1302 			break;
1303 
1304 		case Array::INPUTTYPE_UNSIGNED_SHORT:
1305 			return us.getValue();
1306 			break;
1307 
1308 		case Array::INPUTTYPE_FIXED:
1309 		{
1310 			int maxValue = 65536;
1311 			return (float)(double(2 * fi.getValue() + 1) / (maxValue - 1));
1312 
1313 			break;
1314 		}
1315 
1316 		case Array::INPUTTYPE_UNSIGNED_INT:
1317 			return (float)ui.getValue();
1318 			break;
1319 
1320 		case Array::INPUTTYPE_INT:
1321 			return (float)i.getValue();
1322 			break;
1323 
1324 		case Array::INPUTTYPE_HALF:
1325 			return h.to<float>();
1326 			break;
1327 
1328 		case Array::INPUTTYPE_DOUBLE:
1329 			return (float)d.getValue();
1330 			break;
1331 
1332 		default:
1333 			DE_ASSERT(false);
1334 			return 0.0f;
1335 			break;
1336 	};
1337 }
1338 
1339 class RandomArrayGenerator
1340 {
1341 public:
1342 	static char*	generateArray			(int seed, GLValue min, GLValue max, int count, int componentCount, int stride, Array::InputType type);
1343 	static char*	generateQuads			(int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max);
1344 	static char*	generatePerQuad			(int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max);
1345 
1346 private:
1347 	template<typename T>
1348 	static char*	createQuads		(int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max);
1349 	template<typename T>
1350 	static char*	createPerQuads	(int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max);
1351 	static char*	createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive);
1352 	static void		setData			(char* data, Array::InputType type, deRandom& rnd, GLValue min, GLValue max);
1353 };
1354 
setData(char * data,Array::InputType type,deRandom & rnd,GLValue min,GLValue max)1355 void RandomArrayGenerator::setData (char* data, Array::InputType type, deRandom& rnd, GLValue min, GLValue max)
1356 {
1357 	switch (type)
1358 	{
1359 		case Array::INPUTTYPE_FLOAT:
1360 		{
1361 			alignmentSafeAssignment<float>(data, getRandom<GLValue::Float>(rnd, min.fl, max.fl));
1362 			break;
1363 		}
1364 
1365 		case Array::INPUTTYPE_DOUBLE:
1366 		{
1367 			alignmentSafeAssignment<double>(data, getRandom<GLValue::Float>(rnd, min.fl, max.fl));
1368 			break;
1369 		}
1370 
1371 		case Array::INPUTTYPE_SHORT:
1372 		{
1373 			alignmentSafeAssignment<deInt16>(data, getRandom<GLValue::Short>(rnd, min.s, max.s));
1374 			break;
1375 		}
1376 
1377 		case Array::INPUTTYPE_UNSIGNED_SHORT:
1378 		{
1379 			alignmentSafeAssignment<deUint16>(data, getRandom<GLValue::Ushort>(rnd, min.us, max.us));
1380 			break;
1381 		}
1382 
1383 		case Array::INPUTTYPE_BYTE:
1384 		{
1385 			alignmentSafeAssignment<deInt8>(data, getRandom<GLValue::Byte>(rnd, min.b, max.b));
1386 			break;
1387 		}
1388 
1389 		case Array::INPUTTYPE_UNSIGNED_BYTE:
1390 		{
1391 			alignmentSafeAssignment<deUint8>(data, getRandom<GLValue::Ubyte>(rnd, min.ub, max.ub));
1392 			break;
1393 		}
1394 
1395 		case Array::INPUTTYPE_FIXED:
1396 		{
1397 			alignmentSafeAssignment<deInt32>(data, getRandom<GLValue::Fixed>(rnd, min.fi, max.fi));
1398 			break;
1399 		}
1400 
1401 		case Array::INPUTTYPE_INT:
1402 		{
1403 			alignmentSafeAssignment<deInt32>(data, getRandom<GLValue::Int>(rnd, min.i, max.i));
1404 			break;
1405 		}
1406 
1407 		case Array::INPUTTYPE_UNSIGNED_INT:
1408 		{
1409 			alignmentSafeAssignment<deUint32>(data, getRandom<GLValue::Uint>(rnd, min.ui, max.ui));
1410 			break;
1411 		}
1412 
1413 		case Array::INPUTTYPE_HALF:
1414 		{
1415 			alignmentSafeAssignment<deFloat16>(data, getRandom<GLValue::Half>(rnd, min.h, max.h).getValue());
1416 			break;
1417 		}
1418 
1419 		default:
1420 			DE_ASSERT(false);
1421 			break;
1422 	}
1423 }
1424 
generateArray(int seed,GLValue min,GLValue max,int count,int componentCount,int stride,Array::InputType type)1425 char* RandomArrayGenerator::generateArray (int seed, GLValue min, GLValue max, int count, int componentCount, int stride, Array::InputType type)
1426 {
1427 	char* data = NULL;
1428 
1429 	deRandom rnd;
1430 	deRandom_init(&rnd, seed);
1431 
1432 	if (stride == 0)
1433 		stride = componentCount * Array::inputTypeSize(type);
1434 
1435 	data = new char[stride * count];
1436 
1437 	for (int vertexNdx = 0; vertexNdx < count; vertexNdx++)
1438 	{
1439 		for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1440 		{
1441 			setData(&(data[vertexNdx * stride + Array::inputTypeSize(type) * componentNdx]), type, rnd, min, max);
1442 		}
1443 	}
1444 
1445 	return data;
1446 }
1447 
generateQuads(int seed,int count,int componentCount,int offset,int stride,Array::Primitive primitive,Array::InputType type,GLValue min,GLValue max)1448 char* RandomArrayGenerator::generateQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max)
1449 {
1450 	char* data = DE_NULL;
1451 
1452 	switch (type)
1453 	{
1454 		case Array::INPUTTYPE_FLOAT:
1455 			data = createQuads<GLValue::Float>(seed, count, componentCount, offset, stride, primitive, min.fl, max.fl);
1456 			break;
1457 
1458 		case Array::INPUTTYPE_FIXED:
1459 			data = createQuads<GLValue::Fixed>(seed, count, componentCount, offset, stride, primitive, min.fi, max.fi);
1460 			break;
1461 
1462 		case Array::INPUTTYPE_DOUBLE:
1463 			data = createQuads<GLValue::Double>(seed, count, componentCount, offset, stride, primitive, min.d, max.d);
1464 			break;
1465 
1466 		case Array::INPUTTYPE_BYTE:
1467 			data = createQuads<GLValue::Byte>(seed, count, componentCount, offset, stride, primitive, min.b, max.b);
1468 			break;
1469 
1470 		case Array::INPUTTYPE_SHORT:
1471 			data = createQuads<GLValue::Short>(seed, count, componentCount, offset, stride, primitive, min.s, max.s);
1472 			break;
1473 
1474 		case Array::INPUTTYPE_UNSIGNED_BYTE:
1475 			data = createQuads<GLValue::Ubyte>(seed, count, componentCount, offset, stride, primitive, min.ub, max.ub);
1476 			break;
1477 
1478 		case Array::INPUTTYPE_UNSIGNED_SHORT:
1479 			data = createQuads<GLValue::Ushort>(seed, count, componentCount, offset, stride, primitive, min.us, max.us);
1480 			break;
1481 
1482 		case Array::INPUTTYPE_UNSIGNED_INT:
1483 			data = createQuads<GLValue::Uint>(seed, count, componentCount, offset, stride, primitive, min.ui, max.ui);
1484 			break;
1485 
1486 		case Array::INPUTTYPE_INT:
1487 			data = createQuads<GLValue::Int>(seed, count, componentCount, offset, stride, primitive, min.i, max.i);
1488 			break;
1489 
1490 		case Array::INPUTTYPE_HALF:
1491 			data = createQuads<GLValue::Half>(seed, count, componentCount, offset, stride, primitive, min.h, max.h);
1492 			break;
1493 
1494 		case Array::INPUTTYPE_INT_2_10_10_10:
1495 		case Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10:
1496 			data = createQuadsPacked(seed, count, componentCount, offset, stride, primitive);
1497 			break;
1498 
1499 		default:
1500 			DE_ASSERT(false);
1501 			break;
1502 	}
1503 
1504 	return data;
1505 }
1506 
createQuadsPacked(int seed,int count,int componentCount,int offset,int stride,Array::Primitive primitive)1507 char* RandomArrayGenerator::createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive)
1508 {
1509 	DE_ASSERT(componentCount == 4);
1510 	DE_UNREF(componentCount);
1511 	int quadStride = 0;
1512 
1513 	if (stride == 0)
1514 		stride = sizeof(deUint32);
1515 
1516 	switch (primitive)
1517 	{
1518 		case Array::PRIMITIVE_TRIANGLES:
1519 			quadStride = stride * 6;
1520 			break;
1521 
1522 		default:
1523 			DE_ASSERT(false);
1524 			break;
1525 	}
1526 
1527 	char* const _data		= new char[offset + quadStride * (count - 1) + stride * 5 + componentCount * Array::inputTypeSize(Array::INPUTTYPE_INT_2_10_10_10)]; // last element must be fully in the array
1528 	char* const resultData	= _data + offset;
1529 
1530 	const deUint32 max		= 1024;
1531 	const deUint32 min		= 10;
1532 	const deUint32 max2		= 4;
1533 
1534 	deRandom rnd;
1535 	deRandom_init(&rnd,  seed);
1536 
1537 	switch (primitive)
1538 	{
1539 		case Array::PRIMITIVE_TRIANGLES:
1540 		{
1541 			for (int quadNdx = 0; quadNdx < count; quadNdx++)
1542 			{
1543 				deUint32 x1	= min + deRandom_getUint32(&rnd) % (max - min);
1544 				deUint32 x2	= min + deRandom_getUint32(&rnd) % (max - x1);
1545 
1546 				deUint32 y1	= min + deRandom_getUint32(&rnd) % (max - min);
1547 				deUint32 y2	= min + deRandom_getUint32(&rnd) % (max - y1);
1548 
1549 				deUint32 z	= min + deRandom_getUint32(&rnd) % (max - min);
1550 				deUint32 w	= deRandom_getUint32(&rnd) % max2;
1551 
1552 				deUint32 val1 = (w << 30) | (z << 20) | (y1 << 10) | x1;
1553 				deUint32 val2 = (w << 30) | (z << 20) | (y1 << 10) | x2;
1554 				deUint32 val3 = (w << 30) | (z << 20) | (y2 << 10) | x1;
1555 
1556 				deUint32 val4 = (w << 30) | (z << 20) | (y2 << 10) | x1;
1557 				deUint32 val5 = (w << 30) | (z << 20) | (y1 << 10) | x2;
1558 				deUint32 val6 = (w << 30) | (z << 20) | (y2 << 10) | x2;
1559 
1560 				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 0]), val1);
1561 				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 1]), val2);
1562 				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 2]), val3);
1563 				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 3]), val4);
1564 				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 4]), val5);
1565 				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 5]), val6);
1566 			}
1567 
1568 			break;
1569 		}
1570 
1571 		default:
1572 			DE_ASSERT(false);
1573 			break;
1574 	}
1575 
1576 	return _data;
1577 }
1578 
1579 template<typename T>
createQuads(int seed,int count,int componentCount,int offset,int stride,Array::Primitive primitive,T min,T max)1580 char* RandomArrayGenerator::createQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max)
1581 {
1582 	int componentStride = sizeof(T);
1583 	int quadStride = 0;
1584 
1585 	if (stride == 0)
1586 		stride = componentCount * componentStride;
1587 	DE_ASSERT(stride >= componentCount * componentStride);
1588 
1589 	switch (primitive)
1590 	{
1591 		case Array::PRIMITIVE_TRIANGLES:
1592 			quadStride = stride * 6;
1593 			break;
1594 
1595 		default:
1596 			DE_ASSERT(false);
1597 			break;
1598 	}
1599 
1600 	char* resultData = new char[offset + quadStride * count];
1601 	char* _data = resultData;
1602 	resultData = resultData + offset;
1603 
1604 	deRandom rnd;
1605 	deRandom_init(&rnd,  seed);
1606 
1607 	switch (primitive)
1608 	{
1609 		case Array::PRIMITIVE_TRIANGLES:
1610 		{
1611 			for (int quadNdx = 0; quadNdx < count; ++quadNdx)
1612 			{
1613 				T x1, x2;
1614 				T y1, y2;
1615 				T z, w;
1616 
1617 				// attempt to find a good (i.e not extremely small) quad
1618 				for (int attemptNdx = 0; attemptNdx < 4; ++attemptNdx)
1619 				{
1620 					x1 = getRandom<T>(rnd, min, max);
1621 					x2 = getRandom<T>(rnd, minValue<T>(), abs<T>(max - x1));
1622 
1623 					y1 = getRandom<T>(rnd, min, max);
1624 					y2 = getRandom<T>(rnd, minValue<T>(), abs<T>(max - y1));
1625 
1626 					z = (componentCount > 2) ? (getRandom<T>(rnd, min, max)) : (T::create(0));
1627 					w = (componentCount > 3) ? (getRandom<T>(rnd, min, max)) : (T::create(1));
1628 
1629 					// no additional components, all is good
1630 					if (componentCount <= 2)
1631 						break;
1632 
1633 					// The result quad is too thin?
1634 					if ((deFloatAbs(x2.template to<float>() + z.template to<float>()) < minValue<T>().template to<float>()) ||
1635 						(deFloatAbs(y2.template to<float>() + w.template to<float>()) < minValue<T>().template to<float>()))
1636 						continue;
1637 
1638 					// all ok
1639 					break;
1640 				}
1641 
1642 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride]), x1);
1643 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + componentStride]), y1);
1644 
1645 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride]), x1 + x2);
1646 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride + componentStride]), y1);
1647 
1648 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 2]), x1);
1649 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 2 + componentStride]), y1 + y2);
1650 
1651 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 3]), x1);
1652 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 3 + componentStride]), y1 + y2);
1653 
1654 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 4]), x1 + x2);
1655 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 4 + componentStride]), y1);
1656 
1657 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 5]), x1 + x2);
1658 				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 5 + componentStride]), y1 + y2);
1659 
1660 				if (componentCount > 2)
1661 				{
1662 					for (int i = 0; i < 6; i++)
1663 						alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * i + componentStride * 2]), z);
1664 				}
1665 
1666 				if (componentCount > 3)
1667 				{
1668 					for (int i = 0; i < 6; i++)
1669 						alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * i + componentStride * 3]), w);
1670 				}
1671 			}
1672 
1673 			break;
1674 		}
1675 
1676 		default:
1677 			DE_ASSERT(false);
1678 			break;
1679 	}
1680 
1681 	return _data;
1682 }
1683 
generatePerQuad(int seed,int count,int componentCount,int stride,Array::Primitive primitive,Array::InputType type,GLValue min,GLValue max)1684 char* RandomArrayGenerator::generatePerQuad (int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max)
1685 {
1686 	char* data = DE_NULL;
1687 
1688 	switch (type)
1689 	{
1690 		case Array::INPUTTYPE_FLOAT:
1691 			data = createPerQuads<GLValue::Float>(seed, count, componentCount, stride, primitive, min.fl, max.fl);
1692 			break;
1693 
1694 		case Array::INPUTTYPE_FIXED:
1695 			data = createPerQuads<GLValue::Fixed>(seed, count, componentCount, stride, primitive, min.fi, max.fi);
1696 			break;
1697 
1698 		case Array::INPUTTYPE_DOUBLE:
1699 			data = createPerQuads<GLValue::Double>(seed, count, componentCount, stride, primitive, min.d, max.d);
1700 			break;
1701 
1702 		case Array::INPUTTYPE_BYTE:
1703 			data = createPerQuads<GLValue::Byte>(seed, count, componentCount, stride, primitive, min.b, max.b);
1704 			break;
1705 
1706 		case Array::INPUTTYPE_SHORT:
1707 			data = createPerQuads<GLValue::Short>(seed, count, componentCount, stride, primitive, min.s, max.s);
1708 			break;
1709 
1710 		case Array::INPUTTYPE_UNSIGNED_BYTE:
1711 			data = createPerQuads<GLValue::Ubyte>(seed, count, componentCount, stride, primitive, min.ub, max.ub);
1712 			break;
1713 
1714 		case Array::INPUTTYPE_UNSIGNED_SHORT:
1715 			data = createPerQuads<GLValue::Ushort>(seed, count, componentCount, stride, primitive, min.us, max.us);
1716 			break;
1717 
1718 		case Array::INPUTTYPE_UNSIGNED_INT:
1719 			data = createPerQuads<GLValue::Uint>(seed, count, componentCount, stride, primitive, min.ui, max.ui);
1720 			break;
1721 
1722 		case Array::INPUTTYPE_INT:
1723 			data = createPerQuads<GLValue::Int>(seed, count, componentCount, stride, primitive, min.i, max.i);
1724 			break;
1725 
1726 		case Array::INPUTTYPE_HALF:
1727 			data = createPerQuads<GLValue::Half>(seed, count, componentCount, stride, primitive, min.h, max.h);
1728 			break;
1729 
1730 		default:
1731 			DE_ASSERT(false);
1732 			break;
1733 	}
1734 
1735 	return data;
1736 }
1737 
1738 template<typename T>
createPerQuads(int seed,int count,int componentCount,int stride,Array::Primitive primitive,T min,T max)1739 char* RandomArrayGenerator::createPerQuads (int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max)
1740 {
1741 	deRandom rnd;
1742 	deRandom_init(&rnd, seed);
1743 
1744 	int componentStride = sizeof(T);
1745 
1746 	if (stride == 0)
1747 		stride = componentStride * componentCount;
1748 
1749 	int quadStride = 0;
1750 
1751 	switch (primitive)
1752 	{
1753 		case Array::PRIMITIVE_TRIANGLES:
1754 			quadStride = stride * 6;
1755 			break;
1756 
1757 		default:
1758 			DE_ASSERT(false);
1759 			break;
1760 	}
1761 
1762 	char* data = new char[count * quadStride];
1763 
1764 	for (int quadNdx = 0; quadNdx < count; quadNdx++)
1765 	{
1766 		for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1767 		{
1768 			T val = getRandom<T>(rnd, min, max);
1769 
1770 			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 0 + componentStride * componentNdx, val);
1771 			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 1 + componentStride * componentNdx, val);
1772 			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 2 + componentStride * componentNdx, val);
1773 			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 3 + componentStride * componentNdx, val);
1774 			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 4 + componentStride * componentNdx, val);
1775 			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 5 + componentStride * componentNdx, val);
1776 		}
1777 	}
1778 
1779 	return data;
1780 }
1781 
1782 // VertexArrayTest
1783 
VertexArrayTest(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc)1784 VertexArrayTest::VertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name ,const char* desc)
1785 	: TestCase			(testCtx, name, desc)
1786 	, m_renderCtx		(renderCtx)
1787 	, m_refBuffers		(DE_NULL)
1788 	, m_refContext		(DE_NULL)
1789 	, m_glesContext		(DE_NULL)
1790 	, m_glArrayPack		(DE_NULL)
1791 	, m_rrArrayPack		(DE_NULL)
1792 	, m_isOk			(false)
1793 	, m_maxDiffRed		(deCeilFloatToInt32(256.0f * (2.0f / (1 << m_renderCtx.getRenderTarget().getPixelFormat().redBits))))
1794 	, m_maxDiffGreen	(deCeilFloatToInt32(256.0f * (2.0f / (1 << m_renderCtx.getRenderTarget().getPixelFormat().greenBits))))
1795 	, m_maxDiffBlue		(deCeilFloatToInt32(256.0f * (2.0f / (1 << m_renderCtx.getRenderTarget().getPixelFormat().blueBits))))
1796 {
1797 }
1798 
~VertexArrayTest(void)1799 VertexArrayTest::~VertexArrayTest (void)
1800 {
1801 	deinit();
1802 }
1803 
init(void)1804 void VertexArrayTest::init (void)
1805 {
1806 	const int						renderTargetWidth	= de::min(512, m_renderCtx.getRenderTarget().getWidth());
1807 	const int						renderTargetHeight	= de::min(512, m_renderCtx.getRenderTarget().getHeight());
1808 	sglr::ReferenceContextLimits	limits				(m_renderCtx);
1809 
1810 	m_glesContext		= new sglr::GLContext(m_renderCtx, m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight));
1811 
1812 	m_refBuffers		= new sglr::ReferenceContextBuffers(m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, renderTargetWidth, renderTargetHeight);
1813 	m_refContext		= new sglr::ReferenceContext(limits, m_refBuffers->getColorbuffer(), m_refBuffers->getDepthbuffer(), m_refBuffers->getStencilbuffer());
1814 
1815 	m_glArrayPack		= new ContextArrayPack(m_renderCtx, *m_glesContext);
1816 	m_rrArrayPack		= new ContextArrayPack(m_renderCtx, *m_refContext);
1817 }
1818 
deinit(void)1819 void VertexArrayTest::deinit (void)
1820 {
1821 	delete m_glArrayPack;
1822 	delete m_rrArrayPack;
1823 	delete m_refBuffers;
1824 	delete m_refContext;
1825 	delete m_glesContext;
1826 
1827 	m_glArrayPack	= DE_NULL;
1828 	m_rrArrayPack	= DE_NULL;
1829 	m_refBuffers	= DE_NULL;
1830 	m_refContext	= DE_NULL;
1831 	m_glesContext	= DE_NULL;
1832 }
1833 
compare(void)1834 void VertexArrayTest::compare (void)
1835 {
1836 	const tcu::Surface&	ref		= m_rrArrayPack->getSurface();
1837 	const tcu::Surface&	screen	= m_glArrayPack->getSurface();
1838 
1839 	if (m_renderCtx.getRenderTarget().getNumSamples() > 1)
1840 	{
1841 		// \todo [mika] Improve compare when using multisampling
1842 		m_testCtx.getLog() << tcu::TestLog::Message << "Warning: Comparision of result from multisample render targets are not as stricts as without multisampling. Might produce false positives!" << tcu::TestLog::EndMessage;
1843 		m_isOk = tcu::fuzzyCompare(m_testCtx.getLog(), "Compare Results", "Compare Results", ref.getAccess(), screen.getAccess(), 1.5f, tcu::COMPARE_LOG_RESULT);
1844 	}
1845 	else
1846 	{
1847 		tcu::RGBA		threshold	(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue, 255);
1848 		tcu::Surface	error		(ref.getWidth(), ref.getHeight());
1849 
1850 		m_isOk = true;
1851 
1852 		for (int y = 1; y < ref.getHeight()-1; y++)
1853 		{
1854 			for (int x = 1; x < ref.getWidth()-1; x++)
1855 			{
1856 				tcu::RGBA	refPixel		= ref.getPixel(x, y);
1857 				tcu::RGBA	screenPixel		= screen.getPixel(x, y);
1858 				bool		isOkPixel		= false;
1859 
1860 				// Don't do comparisons for this pixel if it belongs to a one-pixel-thin part (i.e. it doesn't have similar-color neighbors in both x and y directions) in both result and reference.
1861 				// This fixes some false negatives.
1862 				bool		refThin			= (!tcu::compareThreshold(refPixel, ref.getPixel(x-1, y  ), threshold) && !tcu::compareThreshold(refPixel, ref.getPixel(x+1, y  ), threshold)) ||
1863 											  (!tcu::compareThreshold(refPixel, ref.getPixel(x  , y-1), threshold) && !tcu::compareThreshold(refPixel, ref.getPixel(x  , y+1), threshold));
1864 				bool		screenThin		= (!tcu::compareThreshold(screenPixel, screen.getPixel(x-1, y  ), threshold) && !tcu::compareThreshold(screenPixel, screen.getPixel(x+1, y  ), threshold)) ||
1865 											  (!tcu::compareThreshold(screenPixel, screen.getPixel(x  , y-1), threshold) && !tcu::compareThreshold(screenPixel, screen.getPixel(x  , y+1), threshold));
1866 
1867 				if (refThin && screenThin)
1868 					isOkPixel = true;
1869 				else
1870 				{
1871 					for (int dy = -1; dy < 2 && !isOkPixel; dy++)
1872 					{
1873 						for (int dx = -1; dx < 2 && !isOkPixel; dx++)
1874 						{
1875 							// Check reference pixel against screen pixel
1876 							{
1877 								tcu::RGBA	screenCmpPixel	= screen.getPixel(x+dx, y+dy);
1878 								deUint8		r				= deAbs32(refPixel.getRed()		- screenCmpPixel.getRed());
1879 								deUint8		g				= deAbs32(refPixel.getGreen()	- screenCmpPixel.getGreen());
1880 								deUint8		b				= deAbs32(refPixel.getBlue()	- screenCmpPixel.getBlue());
1881 
1882 								if (r <= m_maxDiffRed && g <= m_maxDiffGreen && b <= m_maxDiffBlue)
1883 									isOkPixel = true;
1884 							}
1885 
1886 							// Check screen pixels against reference pixel
1887 							{
1888 								tcu::RGBA	refCmpPixel		= ref.getPixel(x+dx, y+dy);
1889 								deUint8		r				= deAbs32(refCmpPixel.getRed()		- screenPixel.getRed());
1890 								deUint8		g				= deAbs32(refCmpPixel.getGreen()	- screenPixel.getGreen());
1891 								deUint8		b				= deAbs32(refCmpPixel.getBlue()		- screenPixel.getBlue());
1892 
1893 								if (r <= m_maxDiffRed && g <= m_maxDiffGreen && b <= m_maxDiffBlue)
1894 									isOkPixel = true;
1895 							}
1896 						}
1897 					}
1898 				}
1899 
1900 				if (isOkPixel)
1901 					error.setPixel(x, y, tcu::RGBA(screen.getPixel(x, y).getRed(), (screen.getPixel(x, y).getGreen() + 255) / 2, screen.getPixel(x, y).getBlue(), 255));
1902 				else
1903 				{
1904 					error.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
1905 					m_isOk = false;
1906 				}
1907 			}
1908 		}
1909 
1910 		tcu::TestLog& log = m_testCtx.getLog();
1911 		if (!m_isOk)
1912 		{
1913 			log << TestLog::Message << "Image comparison failed, threshold = (" << m_maxDiffRed << ", " << m_maxDiffGreen << ", " << m_maxDiffBlue << ")" << TestLog::EndMessage;
1914 			log << TestLog::ImageSet("Compare result", "Result of rendering")
1915 				<< TestLog::Image("Result",		"Result",		screen)
1916 				<< TestLog::Image("Reference",	"Reference",	ref)
1917 				<< TestLog::Image("ErrorMask",	"Error mask",	error)
1918 				<< TestLog::EndImageSet;
1919 		}
1920 		else
1921 		{
1922 			log << TestLog::ImageSet("Compare result", "Result of rendering")
1923 				<< TestLog::Image("Result", "Result", screen)
1924 				<< TestLog::EndImageSet;
1925 		}
1926 	}
1927 }
1928 
1929 // MultiVertexArrayTest
1930 
ArraySpec(Array::InputType inputType_,Array::OutputType outputType_,Array::Storage storage_,Array::Usage usage_,int componentCount_,int offset_,int stride_,bool normalize_,GLValue min_,GLValue max_)1931 MultiVertexArrayTest::Spec::ArraySpec::ArraySpec(Array::InputType inputType_, Array::OutputType outputType_, Array::Storage storage_, Array::Usage usage_, int componentCount_, int offset_, int stride_, bool normalize_, GLValue min_, GLValue max_)
1932 	: inputType		(inputType_)
1933 	, outputType	(outputType_)
1934 	, storage		(storage_)
1935 	, usage			(usage_)
1936 	, componentCount(componentCount_)
1937 	, offset		(offset_)
1938 	, stride		(stride_)
1939 	, normalize		(normalize_)
1940 	, min			(min_)
1941 	, max			(max_)
1942 {
1943 }
1944 
getName(void) const1945 std::string MultiVertexArrayTest::Spec::getName (void) const
1946 {
1947 	std::stringstream name;
1948 
1949 	for (size_t ndx = 0; ndx < arrays.size(); ++ndx)
1950 	{
1951 		const ArraySpec& array = arrays[ndx];
1952 
1953 		if (arrays.size() > 1)
1954 			name << "array" << ndx << "_";
1955 
1956 		name
1957 			<< Array::storageToString(array.storage) << "_"
1958 			<< array.offset << "_"
1959 			<< array.stride << "_"
1960 			<< Array::inputTypeToString((Array::InputType)array.inputType);
1961 		if (array.inputType != Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 && array.inputType != Array::INPUTTYPE_INT_2_10_10_10)
1962 			name << array.componentCount;
1963 		name
1964 			<< "_"
1965 			<< (array.normalize ? "normalized_" : "")
1966 			<< Array::outputTypeToString(array.outputType) << "_"
1967 			<< Array::usageTypeToString(array.usage) << "_";
1968 	}
1969 
1970 	if (first)
1971 		name << "first" << first << "_";
1972 
1973 	switch (primitive)
1974 	{
1975 		case Array::PRIMITIVE_TRIANGLES:
1976 			name << "quads_";
1977 			break;
1978 		case Array::PRIMITIVE_POINTS:
1979 			name << "points_";
1980 			break;
1981 
1982 		default:
1983 			DE_ASSERT(false);
1984 			break;
1985 	}
1986 
1987 	name << drawCount;
1988 
1989 	return name.str();
1990 }
1991 
getDesc(void) const1992 std::string MultiVertexArrayTest::Spec::getDesc (void) const
1993 {
1994 	std::stringstream desc;
1995 
1996 	for (size_t ndx = 0; ndx < arrays.size(); ++ndx)
1997 	{
1998 		const ArraySpec& array = arrays[ndx];
1999 
2000 		desc
2001 			<< "Array " << ndx << ": "
2002 			<< "Storage in " << Array::storageToString(array.storage) << ", "
2003 			<< "stride " << array.stride << ", "
2004 			<< "input datatype " << Array::inputTypeToString((Array::InputType)array.inputType) << ", "
2005 			<< "input component count " << array.componentCount << ", "
2006 			<< (array.normalize ? "normalized, " : "")
2007 			<< "used as " << Array::outputTypeToString(array.outputType) << ", ";
2008 	}
2009 
2010 	desc
2011 		<< "drawArrays(), "
2012 		<< "first " << first << ", "
2013 		<< drawCount;
2014 
2015 	switch (primitive)
2016 	{
2017 		case Array::PRIMITIVE_TRIANGLES:
2018 			desc << "quads ";
2019 			break;
2020 		case Array::PRIMITIVE_POINTS:
2021 			desc << "points";
2022 			break;
2023 
2024 		default:
2025 			DE_ASSERT(false);
2026 			break;
2027 	}
2028 
2029 
2030 	return desc.str();
2031 }
2032 
MultiVertexArrayTest(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const Spec & spec,const char * name,const char * desc)2033 MultiVertexArrayTest::MultiVertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const Spec& spec, const char* name, const char* desc)
2034 	: VertexArrayTest	(testCtx, renderCtx, name, desc)
2035 	, m_spec			(spec)
2036 	, m_iteration		(0)
2037 {
2038 }
2039 
~MultiVertexArrayTest(void)2040 MultiVertexArrayTest::~MultiVertexArrayTest	(void)
2041 {
2042 }
2043 
iterate(void)2044 MultiVertexArrayTest::IterateResult MultiVertexArrayTest::iterate (void)
2045 {
2046 	if (m_iteration == 0)
2047 	{
2048 		const size_t	primitiveSize		= (m_spec.primitive == Array::PRIMITIVE_TRIANGLES) ? (6) : (1); // in non-indexed draw Triangles means rectangles
2049 		float			coordScale			= 1.0f;
2050 		float			colorScale			= 1.0f;
2051 		const bool		useVao				= m_renderCtx.getType().getProfile() == glu::PROFILE_CORE;
2052 
2053 		// Log info
2054 		m_testCtx.getLog() << TestLog::Message << m_spec.getDesc() << TestLog::EndMessage;
2055 
2056 		// Color and Coord scale
2057 		{
2058 			// First array is always position
2059 			{
2060 				Spec::ArraySpec arraySpec = m_spec.arrays[0];
2061 				if (arraySpec.inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
2062 				{
2063 					if (arraySpec.normalize)
2064 						coordScale = 1.0f;
2065 					else
2066 						coordScale = 1.0 / 1024.0;
2067 				}
2068 				else if (arraySpec.inputType == Array::INPUTTYPE_INT_2_10_10_10)
2069 				{
2070 					if (arraySpec.normalize)
2071 						coordScale = 1.0f;
2072 					else
2073 						coordScale = 1.0 / 512.0;
2074 				}
2075 				else
2076 					coordScale = (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(0.9 / double(arraySpec.max.toFloat())));
2077 
2078 				if (arraySpec.outputType == Array::OUTPUTTYPE_VEC3 || arraySpec.outputType == Array::OUTPUTTYPE_VEC4
2079 					|| arraySpec.outputType == Array::OUTPUTTYPE_IVEC3 || arraySpec.outputType == Array::OUTPUTTYPE_IVEC4
2080 					|| arraySpec.outputType == Array::OUTPUTTYPE_UVEC3 || arraySpec.outputType == Array::OUTPUTTYPE_UVEC4)
2081 						coordScale = coordScale * 0.5f;
2082 			}
2083 
2084 			// And other arrays are color-like
2085 			for (int arrayNdx = 1; arrayNdx < (int)m_spec.arrays.size(); arrayNdx++)
2086 			{
2087 				Spec::ArraySpec arraySpec	= m_spec.arrays[arrayNdx];
2088 
2089 				colorScale *= (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(1.0 / double(arraySpec.max.toFloat())));
2090 				if (arraySpec.outputType == Array::OUTPUTTYPE_VEC4)
2091 					colorScale *= (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(1.0 / double(arraySpec.max.toFloat())));
2092 			}
2093 		}
2094 
2095 		// Data
2096 		for (int arrayNdx = 0; arrayNdx < (int)m_spec.arrays.size(); arrayNdx++)
2097 		{
2098 			Spec::ArraySpec arraySpec		= m_spec.arrays[arrayNdx];
2099 			const int		seed			= int(arraySpec.inputType) + 10 * int(arraySpec.outputType) + 100 * int(arraySpec.storage) + 1000 * int(m_spec.primitive) + 10000 * int(arraySpec.usage) + int(m_spec.drawCount) + 12 * int(arraySpec.componentCount) + int(arraySpec.stride) + int(arraySpec.normalize);
2100 			const char*		data			= DE_NULL;
2101 			const size_t	stride			= (arraySpec.stride == 0) ? (arraySpec.componentCount * Array::inputTypeSize(arraySpec.inputType)) : (arraySpec.stride);
2102 			const size_t	bufferSize		= arraySpec.offset + stride * (m_spec.drawCount * primitiveSize - 1) + arraySpec.componentCount  * Array::inputTypeSize(arraySpec.inputType);
2103 
2104 			switch (m_spec.primitive)
2105 			{
2106 	//			case Array::PRIMITIVE_POINTS:
2107 	//				data = RandomArrayGenerator::generateArray(seed, arraySpec.min, arraySpec.max, arraySpec.count, arraySpec.componentCount, arraySpec.stride, arraySpec.inputType);
2108 	//				break;
2109 				case Array::PRIMITIVE_TRIANGLES:
2110 					if (arrayNdx == 0)
2111 					{
2112 						data = RandomArrayGenerator::generateQuads(seed, m_spec.drawCount, arraySpec.componentCount, arraySpec.offset, arraySpec.stride, m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max);
2113 					}
2114 					else
2115 					{
2116 						DE_ASSERT(arraySpec.offset == 0); // \note [jarkko] it just hasn't been implemented
2117 						data = RandomArrayGenerator::generatePerQuad(seed, m_spec.drawCount, arraySpec.componentCount, arraySpec.stride, m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max);
2118 					}
2119 					break;
2120 
2121 				default:
2122 					DE_ASSERT(false);
2123 					break;
2124 			}
2125 
2126 			m_glArrayPack->newArray(arraySpec.storage);
2127 			m_rrArrayPack->newArray(arraySpec.storage);
2128 
2129 			m_glArrayPack->getArray(arrayNdx)->data(Array::TARGET_ARRAY, (int)bufferSize, data, arraySpec.usage);
2130 			m_rrArrayPack->getArray(arrayNdx)->data(Array::TARGET_ARRAY, (int)bufferSize, data, arraySpec.usage);
2131 
2132 			m_glArrayPack->getArray(arrayNdx)->bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
2133 			m_rrArrayPack->getArray(arrayNdx)->bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
2134 
2135 			delete [] data;
2136 		}
2137 
2138 		try
2139 		{
2140 			m_glArrayPack->render(m_spec.primitive, m_spec.first, m_spec.drawCount * (int)primitiveSize, useVao, coordScale, colorScale);
2141 			m_rrArrayPack->render(m_spec.primitive, m_spec.first, m_spec.drawCount * (int)primitiveSize, useVao, coordScale, colorScale);
2142 		}
2143 		catch (glu::Error& err)
2144 		{
2145 			// GL Errors are ok if the mode is not properly aligned
2146 
2147 			m_testCtx.getLog() << TestLog::Message << "Got error: " << err.what() << TestLog::EndMessage;
2148 
2149 			if (isUnalignedBufferOffsetTest())
2150 				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
2151 			else if (isUnalignedBufferStrideTest())
2152 				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
2153 			else
2154 				throw;
2155 
2156 			return STOP;
2157 		}
2158 
2159 		m_iteration++;
2160 		return CONTINUE;
2161 	}
2162 	else if (m_iteration == 1)
2163 	{
2164 		compare();
2165 
2166 		if (m_isOk)
2167 		{
2168 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2169 		}
2170 		else
2171 		{
2172 			if (isUnalignedBufferOffsetTest())
2173 				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
2174 			else if (isUnalignedBufferStrideTest())
2175 				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
2176 			else
2177 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed.");
2178 		}
2179 
2180 		m_iteration++;
2181 		return STOP;
2182 	}
2183 	else
2184 	{
2185 		DE_ASSERT(false);
2186 		return STOP;
2187 	}
2188 }
2189 
isUnalignedBufferOffsetTest(void) const2190 bool MultiVertexArrayTest::isUnalignedBufferOffsetTest (void) const
2191 {
2192 	// Buffer offsets should be data type size aligned
2193 	for (size_t i = 0; i < m_spec.arrays.size(); ++i)
2194 	{
2195 		if (m_spec.arrays[i].storage == Array::STORAGE_BUFFER)
2196 		{
2197 			const bool inputTypePacked = m_spec.arrays[i].inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_spec.arrays[i].inputType == Array::INPUTTYPE_INT_2_10_10_10;
2198 
2199 			int dataTypeSize = Array::inputTypeSize(m_spec.arrays[i].inputType);
2200 			if (inputTypePacked)
2201 				dataTypeSize = 4;
2202 
2203 			if (m_spec.arrays[i].offset % dataTypeSize != 0)
2204 				return true;
2205 		}
2206 	}
2207 
2208 	return false;
2209 }
2210 
isUnalignedBufferStrideTest(void) const2211 bool MultiVertexArrayTest::isUnalignedBufferStrideTest (void) const
2212 {
2213 	// Buffer strides should be data type size aligned
2214 	for (size_t i = 0; i < m_spec.arrays.size(); ++i)
2215 	{
2216 		if (m_spec.arrays[i].storage == Array::STORAGE_BUFFER)
2217 		{
2218 			const bool inputTypePacked = m_spec.arrays[i].inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_spec.arrays[i].inputType == Array::INPUTTYPE_INT_2_10_10_10;
2219 
2220 			int dataTypeSize = Array::inputTypeSize(m_spec.arrays[i].inputType);
2221 			if (inputTypePacked)
2222 				dataTypeSize = 4;
2223 
2224 			if (m_spec.arrays[i].stride % dataTypeSize != 0)
2225 				return true;
2226 		}
2227 	}
2228 
2229 	return false;
2230 }
2231 
2232 } // gls
2233 } // deqp
2234