1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) Module
3 * -----------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 *//*--------------------------------------------------------------------*/
24 #include "glsDrawTest.hpp"
27 #include "deRandom.hpp"
29 #include "deStringUtil.hpp"
30 #include "deFloat16.h"
31 #include "deUniquePtr.hpp"
32 #include "deArrayUtil.hpp"
34 #include "tcuTestLog.hpp"
35 #include "tcuPixelFormat.hpp"
36 #include "tcuRGBA.hpp"
37 #include "tcuSurface.hpp"
38 #include "tcuVector.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuRenderTarget.hpp"
41 #include "tcuStringTemplate.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuFloat.hpp"
44 #include "tcuTextureUtil.hpp"
46 #include "gluContextInfo.hpp"
47 #include "gluPixelTransfer.hpp"
48 #include "gluCallLogWrapper.hpp"
50 #include "sglrContext.hpp"
51 #include "sglrReferenceContext.hpp"
52 #include "sglrGLContext.hpp"
54 #include "rrGenericVector.hpp"
62 #include "glwDefs.hpp"
63 #include "glwEnums.hpp"
73 using namespace glw; // GL types
75 const int MAX_RENDER_TARGET_SIZE = 512;
79 static GLenum targetToGL (DrawTestSpec::Target target)
81 static const GLenum targets[] =
83 GL_ELEMENT_ARRAY_BUFFER, // TARGET_ELEMENT_ARRAY = 0,
84 GL_ARRAY_BUFFER // TARGET_ARRAY,
87 return de::getSizedArrayElement<DrawTestSpec::TARGET_LAST>(targets, (int)target);
90 static GLenum usageToGL (DrawTestSpec::Usage usage)
92 static const GLenum usages[] =
94 GL_DYNAMIC_DRAW, // USAGE_DYNAMIC_DRAW = 0,
95 GL_STATIC_DRAW, // USAGE_STATIC_DRAW,
96 GL_STREAM_DRAW, // USAGE_STREAM_DRAW,
98 GL_STREAM_READ, // USAGE_STREAM_READ,
99 GL_STREAM_COPY, // USAGE_STREAM_COPY,
101 GL_STATIC_READ, // USAGE_STATIC_READ,
102 GL_STATIC_COPY, // USAGE_STATIC_COPY,
104 GL_DYNAMIC_READ, // USAGE_DYNAMIC_READ,
105 GL_DYNAMIC_COPY // USAGE_DYNAMIC_COPY,
108 return de::getSizedArrayElement<DrawTestSpec::USAGE_LAST>(usages, (int)usage);
111 static GLenum inputTypeToGL (DrawTestSpec::InputType type)
113 static const GLenum types[] =
115 GL_FLOAT, // INPUTTYPE_FLOAT = 0,
116 GL_FIXED, // INPUTTYPE_FIXED,
117 GL_DOUBLE, // INPUTTYPE_DOUBLE
118 GL_BYTE, // INPUTTYPE_BYTE,
119 GL_SHORT, // INPUTTYPE_SHORT,
120 GL_UNSIGNED_BYTE, // INPUTTYPE_UNSIGNED_BYTE,
121 GL_UNSIGNED_SHORT, // INPUTTYPE_UNSIGNED_SHORT,
123 GL_INT, // INPUTTYPE_INT,
124 GL_UNSIGNED_INT, // INPUTTYPE_UNSIGNED_INT,
125 GL_HALF_FLOAT, // INPUTTYPE_HALF,
126 GL_UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
127 GL_INT_2_10_10_10_REV // INPUTTYPE_INT_2_10_10_10,
130 return de::getSizedArrayElement<DrawTestSpec::INPUTTYPE_LAST>(types, (int)type);
133 static std::string outputTypeToGLType (DrawTestSpec::OutputType type)
135 static const char* types[] =
137 "float", // OUTPUTTYPE_FLOAT = 0,
138 "vec2", // OUTPUTTYPE_VEC2,
139 "vec3", // OUTPUTTYPE_VEC3,
140 "vec4", // OUTPUTTYPE_VEC4,
142 "int", // OUTPUTTYPE_INT,
143 "uint", // OUTPUTTYPE_UINT,
145 "ivec2", // OUTPUTTYPE_IVEC2,
146 "ivec3", // OUTPUTTYPE_IVEC3,
147 "ivec4", // OUTPUTTYPE_IVEC4,
149 "uvec2", // OUTPUTTYPE_UVEC2,
150 "uvec3", // OUTPUTTYPE_UVEC3,
151 "uvec4", // OUTPUTTYPE_UVEC4,
154 return de::getSizedArrayElement<DrawTestSpec::OUTPUTTYPE_LAST>(types, (int)type);
157 static GLenum primitiveToGL (DrawTestSpec::Primitive primitive)
159 static const GLenum primitives[] =
161 GL_POINTS, // PRIMITIVE_POINTS = 0,
162 GL_TRIANGLES, // PRIMITIVE_TRIANGLES,
163 GL_TRIANGLE_FAN, // PRIMITIVE_TRIANGLE_FAN,
164 GL_TRIANGLE_STRIP, // PRIMITIVE_TRIANGLE_STRIP,
165 GL_LINES, // PRIMITIVE_LINES
166 GL_LINE_STRIP, // PRIMITIVE_LINE_STRIP
167 GL_LINE_LOOP, // PRIMITIVE_LINE_LOOP
168 GL_LINES_ADJACENCY, // PRIMITIVE_LINES_ADJACENCY
169 GL_LINE_STRIP_ADJACENCY, // PRIMITIVE_LINE_STRIP_ADJACENCY
170 GL_TRIANGLES_ADJACENCY, // PRIMITIVE_TRIANGLES_ADJACENCY
171 GL_TRIANGLE_STRIP_ADJACENCY, // PRIMITIVE_TRIANGLE_STRIP_ADJACENCY
174 return de::getSizedArrayElement<DrawTestSpec::PRIMITIVE_LAST>(primitives, (int)primitive);
177 static deUint32 indexTypeToGL (DrawTestSpec::IndexType indexType)
179 static const GLenum indexTypes[] =
181 GL_UNSIGNED_BYTE, // INDEXTYPE_BYTE = 0,
182 GL_UNSIGNED_SHORT, // INDEXTYPE_SHORT,
183 GL_UNSIGNED_INT, // INDEXTYPE_INT,
186 return de::getSizedArrayElement<DrawTestSpec::INDEXTYPE_LAST>(indexTypes, (int)indexType);
189 static bool inputTypeIsFloatType (DrawTestSpec::InputType type)
191 if (type == DrawTestSpec::INPUTTYPE_FLOAT)
193 if (type == DrawTestSpec::INPUTTYPE_FIXED)
195 if (type == DrawTestSpec::INPUTTYPE_HALF)
197 if (type == DrawTestSpec::INPUTTYPE_DOUBLE)
202 static bool outputTypeIsFloatType (DrawTestSpec::OutputType type)
204 if (type == DrawTestSpec::OUTPUTTYPE_FLOAT
205 || type == DrawTestSpec::OUTPUTTYPE_VEC2
206 || type == DrawTestSpec::OUTPUTTYPE_VEC3
207 || type == DrawTestSpec::OUTPUTTYPE_VEC4)
213 static bool outputTypeIsIntType (DrawTestSpec::OutputType type)
215 if (type == DrawTestSpec::OUTPUTTYPE_INT
216 || type == DrawTestSpec::OUTPUTTYPE_IVEC2
217 || type == DrawTestSpec::OUTPUTTYPE_IVEC3
218 || type == DrawTestSpec::OUTPUTTYPE_IVEC4)
224 static bool outputTypeIsUintType (DrawTestSpec::OutputType type)
226 if (type == DrawTestSpec::OUTPUTTYPE_UINT
227 || type == DrawTestSpec::OUTPUTTYPE_UVEC2
228 || type == DrawTestSpec::OUTPUTTYPE_UVEC3
229 || type == DrawTestSpec::OUTPUTTYPE_UVEC4)
235 static size_t getElementCount (DrawTestSpec::Primitive primitive, size_t primitiveCount)
239 case DrawTestSpec::PRIMITIVE_POINTS: return primitiveCount;
240 case DrawTestSpec::PRIMITIVE_TRIANGLES: return primitiveCount * 3;
241 case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN: return primitiveCount + 2;
242 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP: return primitiveCount + 2;
243 case DrawTestSpec::PRIMITIVE_LINES: return primitiveCount * 2;
244 case DrawTestSpec::PRIMITIVE_LINE_STRIP: return primitiveCount + 1;
245 case DrawTestSpec::PRIMITIVE_LINE_LOOP: return (primitiveCount==1) ? (2) : (primitiveCount);
246 case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY: return primitiveCount * 4;
247 case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY: return primitiveCount + 3;
248 case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY: return primitiveCount * 6;
249 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY: return primitiveCount * 2 + 4;
266 static MethodInfo getMethodInfo (gls::DrawTestSpec::DrawMethod method)
268 static const MethodInfo infos[] =
270 // indexed instanced ranged first baseVertex indirect
271 { false, false, false, true, false, false }, //!< DRAWMETHOD_DRAWARRAYS,
272 { false, true, false, true, false, false }, //!< DRAWMETHOD_DRAWARRAYS_INSTANCED,
273 { false, true, false, true, false, true }, //!< DRAWMETHOD_DRAWARRAYS_INDIRECT,
274 { true, false, false, false, false, false }, //!< DRAWMETHOD_DRAWELEMENTS,
275 { true, false, true, false, false, false }, //!< DRAWMETHOD_DRAWELEMENTS_RANGED,
276 { true, true, false, false, false, false }, //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED,
277 { true, true, false, false, true, true }, //!< DRAWMETHOD_DRAWELEMENTS_INDIRECT,
278 { true, false, false, false, true, false }, //!< DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
279 { true, true, false, false, true, false }, //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
280 { true, false, true, false, true, false }, //!< DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
283 return de::getSizedArrayElement<DrawTestSpec::DRAWMETHOD_LAST>(infos, (int)method);
287 inline static void alignmentSafeAssignment (char* dst, T val)
289 std::memcpy(dst, &val, sizeof(T));
292 static bool checkSpecsShaderCompatible (const DrawTestSpec& a, const DrawTestSpec& b)
294 // Only the attributes matter
295 if (a.attribs.size() != b.attribs.size())
298 for (size_t ndx = 0; ndx < a.attribs.size(); ++ndx)
300 // Only the output type (== shader input type) matters and the usage in the shader.
302 if (a.attribs[ndx].additionalPositionAttribute != b.attribs[ndx].additionalPositionAttribute)
305 // component counts need not to match
306 if (outputTypeIsFloatType(a.attribs[ndx].outputType) && outputTypeIsFloatType(b.attribs[ndx].outputType))
308 if (outputTypeIsIntType(a.attribs[ndx].outputType) && outputTypeIsIntType(b.attribs[ndx].outputType))
310 if (outputTypeIsUintType(a.attribs[ndx].outputType) && outputTypeIsUintType(b.attribs[ndx].outputType))
319 // generate random vectors in a way that does not depend on argument evaluation order
321 tcu::Vec4 generateRandomVec4 (de::Random& random)
325 for (int i = 0; i < 4; ++i)
326 retVal[i] = random.getFloat();
331 tcu::IVec4 generateRandomIVec4 (de::Random& random)
335 for (int i = 0; i < 4; ++i)
336 retVal[i] = random.getUint32();
341 tcu::UVec4 generateRandomUVec4 (de::Random& random)
345 for (int i = 0; i < 4; ++i)
346 retVal[i] = random.getUint32();
351 // IterationLogSectionEmitter
353 class IterationLogSectionEmitter
356 IterationLogSectionEmitter (tcu::TestLog& log, size_t testIteration, size_t testIterations, const std::string& description, bool enabled);
357 ~IterationLogSectionEmitter (void);
359 IterationLogSectionEmitter (const IterationLogSectionEmitter&); // delete
360 IterationLogSectionEmitter& operator= (const IterationLogSectionEmitter&); // delete
366 IterationLogSectionEmitter::IterationLogSectionEmitter (tcu::TestLog& log, size_t testIteration, size_t testIterations, const std::string& description, bool enabled)
368 , m_enabled (enabled)
372 std::ostringstream buf;
373 buf << "Iteration " << (testIteration+1) << "/" << testIterations;
375 if (!description.empty())
376 buf << " - " << description;
378 m_log << tcu::TestLog::Section(buf.str(), buf.str());
382 IterationLogSectionEmitter::~IterationLogSectionEmitter (void)
385 m_log << tcu::TestLog::EndSection;
398 static WrappedType<Type> create (Type value) { WrappedType<Type> v; v.m_value = value; return v; }
399 inline Type getValue (void) const { return m_value; }
401 inline WrappedType<Type> operator+ (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value + other.getValue())); }
402 inline WrappedType<Type> operator* (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value * other.getValue())); }
403 inline WrappedType<Type> operator/ (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value / other.getValue())); }
404 inline WrappedType<Type> operator- (const WrappedType<Type>& other) const { return WrappedType<Type>::create((Type)(m_value - other.getValue())); }
406 inline WrappedType<Type>& operator+= (const WrappedType<Type>& other) { m_value += other.getValue(); return *this; }
407 inline WrappedType<Type>& operator*= (const WrappedType<Type>& other) { m_value *= other.getValue(); return *this; }
408 inline WrappedType<Type>& operator/= (const WrappedType<Type>& other) { m_value /= other.getValue(); return *this; }
409 inline WrappedType<Type>& operator-= (const WrappedType<Type>& other) { m_value -= other.getValue(); return *this; }
411 inline bool operator== (const WrappedType<Type>& other) const { return m_value == other.m_value; }
412 inline bool operator!= (const WrappedType<Type>& other) const { return m_value != other.m_value; }
413 inline bool operator< (const WrappedType<Type>& other) const { return m_value < other.m_value; }
414 inline bool operator> (const WrappedType<Type>& other) const { return m_value > other.m_value; }
415 inline bool operator<= (const WrappedType<Type>& other) const { return m_value <= other.m_value; }
416 inline bool operator>= (const WrappedType<Type>& other) const { return m_value >= other.m_value; }
418 inline operator Type (void) const { return m_value; }
420 inline T to (void) const { return (T)m_value; }
425 typedef WrappedType<deInt16> Short;
426 typedef WrappedType<deUint16> Ushort;
428 typedef WrappedType<deInt8> Byte;
429 typedef WrappedType<deUint8> Ubyte;
431 typedef WrappedType<float> Float;
432 typedef WrappedType<double> Double;
434 typedef WrappedType<deInt32> Int;
435 typedef WrappedType<deUint32> Uint;
440 static Half create (float value) { Half h; h.m_value = floatToHalf(value); return h; }
441 inline deFloat16 getValue (void) const { return m_value; }
443 inline Half operator+ (const Half& other) const { return create(halfToFloat(m_value) + halfToFloat(other.getValue())); }
444 inline Half operator* (const Half& other) const { return create(halfToFloat(m_value) * halfToFloat(other.getValue())); }
445 inline Half operator/ (const Half& other) const { return create(halfToFloat(m_value) / halfToFloat(other.getValue())); }
446 inline Half operator- (const Half& other) const { return create(halfToFloat(m_value) - halfToFloat(other.getValue())); }
448 inline Half& operator+= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) + halfToFloat(m_value)); return *this; }
449 inline Half& operator*= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) * halfToFloat(m_value)); return *this; }
450 inline Half& operator/= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) / halfToFloat(m_value)); return *this; }
451 inline Half& operator-= (const Half& other) { m_value = floatToHalf(halfToFloat(other.getValue()) - halfToFloat(m_value)); return *this; }
453 inline bool operator== (const Half& other) const { return m_value == other.m_value; }
454 inline bool operator!= (const Half& other) const { return m_value != other.m_value; }
455 inline bool operator< (const Half& other) const { return halfToFloat(m_value) < halfToFloat(other.m_value); }
456 inline bool operator> (const Half& other) const { return halfToFloat(m_value) > halfToFloat(other.m_value); }
457 inline bool operator<= (const Half& other) const { return halfToFloat(m_value) <= halfToFloat(other.m_value); }
458 inline bool operator>= (const Half& other) const { return halfToFloat(m_value) >= halfToFloat(other.m_value); }
461 inline T to (void) const { return (T)halfToFloat(m_value); }
463 inline static deFloat16 floatToHalf (float f);
464 inline static float halfToFloat (deFloat16 h);
472 static Fixed create (deInt32 value) { Fixed v; v.m_value = value; return v; }
473 inline deInt32 getValue (void) const { return m_value; }
475 inline Fixed operator+ (const Fixed& other) const { return create(m_value + other.getValue()); }
476 inline Fixed operator* (const Fixed& other) const { return create(m_value * other.getValue()); }
477 inline Fixed operator/ (const Fixed& other) const { return create(m_value / other.getValue()); }
478 inline Fixed operator- (const Fixed& other) const { return create(m_value - other.getValue()); }
480 inline Fixed& operator+= (const Fixed& other) { m_value += other.getValue(); return *this; }
481 inline Fixed& operator*= (const Fixed& other) { m_value *= other.getValue(); return *this; }
482 inline Fixed& operator/= (const Fixed& other) { m_value /= other.getValue(); return *this; }
483 inline Fixed& operator-= (const Fixed& other) { m_value -= other.getValue(); return *this; }
485 inline bool operator== (const Fixed& other) const { return m_value == other.m_value; }
486 inline bool operator!= (const Fixed& other) const { return m_value != other.m_value; }
487 inline bool operator< (const Fixed& other) const { return m_value < other.m_value; }
488 inline bool operator> (const Fixed& other) const { return m_value > other.m_value; }
489 inline bool operator<= (const Fixed& other) const { return m_value <= other.m_value; }
490 inline bool operator>= (const Fixed& other) const { return m_value >= other.m_value; }
492 inline operator deInt32 (void) const { return m_value; }
494 inline T to (void) const { return (T)m_value; }
499 // \todo [mika] This is pretty messy
500 GLValue (void) : type(DrawTestSpec::INPUTTYPE_LAST) {}
501 explicit GLValue (Float value) : type(DrawTestSpec::INPUTTYPE_FLOAT), fl(value) {}
502 explicit GLValue (Fixed value) : type(DrawTestSpec::INPUTTYPE_FIXED), fi(value) {}
503 explicit GLValue (Byte value) : type(DrawTestSpec::INPUTTYPE_BYTE), b(value) {}
504 explicit GLValue (Ubyte value) : type(DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE), ub(value) {}
505 explicit GLValue (Short value) : type(DrawTestSpec::INPUTTYPE_SHORT), s(value) {}
506 explicit GLValue (Ushort value) : type(DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT), us(value) {}
507 explicit GLValue (Int value) : type(DrawTestSpec::INPUTTYPE_INT), i(value) {}
508 explicit GLValue (Uint value) : type(DrawTestSpec::INPUTTYPE_UNSIGNED_INT), ui(value) {}
509 explicit GLValue (Half value) : type(DrawTestSpec::INPUTTYPE_HALF), h(value) {}
510 explicit GLValue (Double value) : type(DrawTestSpec::INPUTTYPE_DOUBLE), d(value) {}
512 float toFloat (void) const;
514 static GLValue getMaxValue (DrawTestSpec::InputType type);
515 static GLValue getMinValue (DrawTestSpec::InputType type);
517 DrawTestSpec::InputType type;
534 inline deFloat16 GLValue::Half::floatToHalf (float f)
536 // No denorm support.
537 tcu::Float<deUint16, 5, 10, 15, tcu::FLOAT_HAS_SIGN> v(f);
538 DE_ASSERT(!v.isNaN() && !v.isInf());
542 inline float GLValue::Half::halfToFloat (deFloat16 h)
544 return tcu::Float16((deUint16)h).asFloat();
547 float GLValue::toFloat (void) const
551 case DrawTestSpec::INPUTTYPE_FLOAT:
552 return fl.getValue();
555 case DrawTestSpec::INPUTTYPE_BYTE:
559 case DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE:
560 return ub.getValue();
563 case DrawTestSpec::INPUTTYPE_SHORT:
567 case DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT:
568 return us.getValue();
571 case DrawTestSpec::INPUTTYPE_FIXED:
573 int maxValue = 65536;
574 return (float)(double(2 * fi.getValue() + 1) / (maxValue - 1));
579 case DrawTestSpec::INPUTTYPE_UNSIGNED_INT:
580 return (float)ui.getValue();
583 case DrawTestSpec::INPUTTYPE_INT:
584 return (float)i.getValue();
587 case DrawTestSpec::INPUTTYPE_HALF:
588 return h.to<float>();
591 case DrawTestSpec::INPUTTYPE_DOUBLE:
592 return d.to<float>();
602 GLValue GLValue::getMaxValue (DrawTestSpec::InputType type)
604 GLValue rangesHi[(int)DrawTestSpec::INPUTTYPE_LAST];
606 rangesHi[(int)DrawTestSpec::INPUTTYPE_FLOAT] = GLValue(Float::create(127.0f));
607 rangesHi[(int)DrawTestSpec::INPUTTYPE_DOUBLE] = GLValue(Double::create(127.0f));
608 rangesHi[(int)DrawTestSpec::INPUTTYPE_BYTE] = GLValue(Byte::create(127));
609 rangesHi[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE] = GLValue(Ubyte::create(255));
610 rangesHi[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT] = GLValue(Ushort::create(65530));
611 rangesHi[(int)DrawTestSpec::INPUTTYPE_SHORT] = GLValue(Short::create(32760));
612 rangesHi[(int)DrawTestSpec::INPUTTYPE_FIXED] = GLValue(Fixed::create(32760));
613 rangesHi[(int)DrawTestSpec::INPUTTYPE_INT] = GLValue(Int::create(2147483647));
614 rangesHi[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_INT] = GLValue(Uint::create(4294967295u));
615 rangesHi[(int)DrawTestSpec::INPUTTYPE_HALF] = GLValue(Half::create(256.0f));
617 return rangesHi[(int)type];
620 GLValue GLValue::getMinValue (DrawTestSpec::InputType type)
622 GLValue rangesLo[(int)DrawTestSpec::INPUTTYPE_LAST];
624 rangesLo[(int)DrawTestSpec::INPUTTYPE_FLOAT] = GLValue(Float::create(-127.0f));
625 rangesLo[(int)DrawTestSpec::INPUTTYPE_DOUBLE] = GLValue(Double::create(-127.0f));
626 rangesLo[(int)DrawTestSpec::INPUTTYPE_BYTE] = GLValue(Byte::create(-127));
627 rangesLo[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE] = GLValue(Ubyte::create(0));
628 rangesLo[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT] = GLValue(Ushort::create(0));
629 rangesLo[(int)DrawTestSpec::INPUTTYPE_SHORT] = GLValue(Short::create(-32760));
630 rangesLo[(int)DrawTestSpec::INPUTTYPE_FIXED] = GLValue(Fixed::create(-32760));
631 rangesLo[(int)DrawTestSpec::INPUTTYPE_INT] = GLValue(Int::create(-2147483647));
632 rangesLo[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_INT] = GLValue(Uint::create(0));
633 rangesLo[(int)DrawTestSpec::INPUTTYPE_HALF] = GLValue(Half::create(-256.0f));
635 return rangesLo[(int)type];
639 struct GLValueTypeTraits;
641 template<> struct GLValueTypeTraits<GLValue::Float> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_FLOAT; };
642 template<> struct GLValueTypeTraits<GLValue::Double> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_DOUBLE; };
643 template<> struct GLValueTypeTraits<GLValue::Byte> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_BYTE; };
644 template<> struct GLValueTypeTraits<GLValue::Ubyte> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE; };
645 template<> struct GLValueTypeTraits<GLValue::Ushort> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT; };
646 template<> struct GLValueTypeTraits<GLValue::Short> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_SHORT; };
647 template<> struct GLValueTypeTraits<GLValue::Fixed> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_FIXED; };
648 template<> struct GLValueTypeTraits<GLValue::Int> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_INT; };
649 template<> struct GLValueTypeTraits<GLValue::Uint> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_UNSIGNED_INT; };
650 template<> struct GLValueTypeTraits<GLValue::Half> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_HALF; };
653 inline T extractGLValue (const GLValue& v);
655 template<> GLValue::Float inline extractGLValue<GLValue::Float> (const GLValue& v) { return v.fl; };
656 template<> GLValue::Double inline extractGLValue<GLValue::Double> (const GLValue& v) { return v.d; };
657 template<> GLValue::Byte inline extractGLValue<GLValue::Byte> (const GLValue& v) { return v.b; };
658 template<> GLValue::Ubyte inline extractGLValue<GLValue::Ubyte> (const GLValue& v) { return v.ub; };
659 template<> GLValue::Ushort inline extractGLValue<GLValue::Ushort> (const GLValue& v) { return v.us; };
660 template<> GLValue::Short inline extractGLValue<GLValue::Short> (const GLValue& v) { return v.s; };
661 template<> GLValue::Fixed inline extractGLValue<GLValue::Fixed> (const GLValue& v) { return v.fi; };
662 template<> GLValue::Int inline extractGLValue<GLValue::Int> (const GLValue& v) { return v.i; };
663 template<> GLValue::Uint inline extractGLValue<GLValue::Uint> (const GLValue& v) { return v.ui; };
664 template<> GLValue::Half inline extractGLValue<GLValue::Half> (const GLValue& v) { return v.h; };
667 inline T getRandom (deRandom& rnd, T min, T max);
670 inline GLValue::Float getRandom (deRandom& rnd, GLValue::Float min, GLValue::Float max)
675 return GLValue::Float::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
679 inline GLValue::Double getRandom (deRandom& rnd, GLValue::Double min, GLValue::Double max)
684 return GLValue::Double::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
688 inline GLValue::Short getRandom (deRandom& rnd, GLValue::Short min, GLValue::Short max)
693 return GLValue::Short::create((min == max ? min : (deInt16)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
697 inline GLValue::Ushort getRandom (deRandom& rnd, GLValue::Ushort min, GLValue::Ushort max)
702 return GLValue::Ushort::create((min == max ? min : (deUint16)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
706 inline GLValue::Byte getRandom (deRandom& rnd, GLValue::Byte min, GLValue::Byte max)
711 return GLValue::Byte::create((min == max ? min : (deInt8)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
715 inline GLValue::Ubyte getRandom (deRandom& rnd, GLValue::Ubyte min, GLValue::Ubyte max)
720 return GLValue::Ubyte::create((min == max ? min : (deUint8)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
724 inline GLValue::Fixed getRandom (deRandom& rnd, GLValue::Fixed min, GLValue::Fixed max)
729 return GLValue::Fixed::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
733 inline GLValue::Half getRandom (deRandom& rnd, GLValue::Half min, GLValue::Half max)
738 float fMax = max.to<float>();
739 float fMin = min.to<float>();
740 GLValue::Half h = GLValue::Half::create(fMin + deRandom_getFloat(&rnd) * (fMax - fMin));
745 inline GLValue::Int getRandom (deRandom& rnd, GLValue::Int min, GLValue::Int max)
750 return GLValue::Int::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
754 inline GLValue::Uint getRandom (deRandom& rnd, GLValue::Uint min, GLValue::Uint max)
759 return GLValue::Uint::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
762 // Minimum difference required between coordinates
764 inline T minValue (void);
767 inline GLValue::Float minValue (void)
769 return GLValue::Float::create(4 * 1.0f);
773 inline GLValue::Double minValue (void)
775 return GLValue::Double::create(4 * 1.0f);
779 inline GLValue::Short minValue (void)
781 return GLValue::Short::create(4 * 256);
785 inline GLValue::Ushort minValue (void)
787 return GLValue::Ushort::create(4 * 256);
791 inline GLValue::Byte minValue (void)
793 return GLValue::Byte::create(4 * 1);
797 inline GLValue::Ubyte minValue (void)
799 return GLValue::Ubyte::create(4 * 2);
803 inline GLValue::Fixed minValue (void)
805 return GLValue::Fixed::create(4 * 1);
809 inline GLValue::Int minValue (void)
811 return GLValue::Int::create(4 * 16777216);
815 inline GLValue::Uint minValue (void)
817 return GLValue::Uint::create(4 * 16777216);
821 inline GLValue::Half minValue (void)
823 return GLValue::Half::create(4 * 1.0f);
827 inline T abs (T val);
830 inline GLValue::Fixed abs (GLValue::Fixed val)
832 return GLValue::Fixed::create(0x7FFFu & val.getValue());
836 inline GLValue::Ubyte abs (GLValue::Ubyte val)
842 inline GLValue::Byte abs (GLValue::Byte val)
844 return GLValue::Byte::create(0x7Fu & val.getValue());
848 inline GLValue::Ushort abs (GLValue::Ushort val)
854 inline GLValue::Short abs (GLValue::Short val)
856 return GLValue::Short::create(0x7FFFu & val.getValue());
860 inline GLValue::Float abs (GLValue::Float val)
862 return GLValue::Float::create(std::fabs(val.to<float>()));
866 inline GLValue::Double abs (GLValue::Double val)
868 return GLValue::Double::create(std::fabs(val.to<float>()));
872 inline GLValue::Uint abs (GLValue::Uint val)
878 inline GLValue::Int abs (GLValue::Int val)
880 return GLValue::Int::create(0x7FFFFFFFu & val.getValue());
884 inline GLValue::Half abs (GLValue::Half val)
886 return GLValue::Half::create(std::fabs(val.to<float>()));
894 AttributeArray (DrawTestSpec::Storage storage, sglr::Context& context);
895 ~AttributeArray (void);
897 void data (DrawTestSpec::Target target, size_t size, const char* data, DrawTestSpec::Usage usage);
898 void setupArray (bool bound, int offset, int size, DrawTestSpec::InputType inType, DrawTestSpec::OutputType outType, bool normalized, int stride, int instanceDivisor, const rr::GenericVec4& defaultAttrib, bool isPositionAttr, bool bgraComponentOrder);
899 void bindAttribute (deUint32 loc);
900 void bindIndexArray (DrawTestSpec::Target storage);
902 int getComponentCount (void) const { return m_componentCount; }
903 DrawTestSpec::Target getTarget (void) const { return m_target; }
904 DrawTestSpec::InputType getInputType (void) const { return m_inputType; }
905 DrawTestSpec::OutputType getOutputType (void) const { return m_outputType; }
906 DrawTestSpec::Storage getStorageType (void) const { return m_storage; }
907 bool getNormalized (void) const { return m_normalize; }
908 int getStride (void) const { return m_stride; }
909 bool isBound (void) const { return m_bound; }
910 bool isPositionAttribute (void) const { return m_isPositionAttr; }
913 DrawTestSpec::Storage m_storage;
914 sglr::Context& m_ctx;
919 int m_componentCount;
921 DrawTestSpec::Target m_target;
922 DrawTestSpec::InputType m_inputType;
923 DrawTestSpec::OutputType m_outputType;
927 rr::GenericVec4 m_defaultAttrib;
928 int m_instanceDivisor;
929 bool m_isPositionAttr;
933 AttributeArray::AttributeArray (DrawTestSpec::Storage storage, sglr::Context& context)
934 : m_storage (storage)
939 , m_componentCount (1)
941 , m_target (DrawTestSpec::TARGET_ARRAY)
942 , m_inputType (DrawTestSpec::INPUTTYPE_FLOAT)
943 , m_outputType (DrawTestSpec::OUTPUTTYPE_VEC4)
944 , m_normalize (false)
947 , m_instanceDivisor (0)
948 , m_isPositionAttr (false)
949 , m_bgraOrder (false)
951 if (m_storage == DrawTestSpec::STORAGE_BUFFER)
953 m_ctx.genBuffers(1, &m_glBuffer);
954 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glGenBuffers()");
958 AttributeArray::~AttributeArray (void)
960 if (m_storage == DrawTestSpec::STORAGE_BUFFER)
962 m_ctx.deleteBuffers(1, &m_glBuffer);
963 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDeleteBuffers()");
965 else if (m_storage == DrawTestSpec::STORAGE_USER)
971 void AttributeArray::data (DrawTestSpec::Target target, size_t size, const char* ptr, DrawTestSpec::Usage usage)
976 if (m_storage == DrawTestSpec::STORAGE_BUFFER)
978 m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
979 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
981 m_ctx.bufferData(targetToGL(target), size, ptr, usageToGL(usage));
982 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferData()");
984 else if (m_storage == DrawTestSpec::STORAGE_USER)
989 m_data = new char[size];
990 std::memcpy(m_data, ptr, size);
996 void AttributeArray::setupArray (bool bound, int offset, int size, DrawTestSpec::InputType inputType, DrawTestSpec::OutputType outType, bool normalized, int stride, int instanceDivisor, const rr::GenericVec4& defaultAttrib, bool isPositionAttr, bool bgraComponentOrder)
998 m_componentCount = size;
1000 m_inputType = inputType;
1001 m_outputType = outType;
1002 m_normalize = normalized;
1005 m_defaultAttrib = defaultAttrib;
1006 m_instanceDivisor = instanceDivisor;
1007 m_isPositionAttr = isPositionAttr;
1008 m_bgraOrder = bgraComponentOrder;
1011 void AttributeArray::bindAttribute (deUint32 loc)
1015 switch (m_inputType)
1017 case DrawTestSpec::INPUTTYPE_FLOAT:
1019 tcu::Vec4 attr = m_defaultAttrib.get<float>();
1021 switch (m_componentCount)
1023 case 1: m_ctx.vertexAttrib1f(loc, attr.x()); break;
1024 case 2: m_ctx.vertexAttrib2f(loc, attr.x(), attr.y()); break;
1025 case 3: m_ctx.vertexAttrib3f(loc, attr.x(), attr.y(), attr.z()); break;
1026 case 4: m_ctx.vertexAttrib4f(loc, attr.x(), attr.y(), attr.z(), attr.w()); break;
1027 default: DE_ASSERT(DE_FALSE); break;
1031 case DrawTestSpec::INPUTTYPE_INT:
1033 tcu::IVec4 attr = m_defaultAttrib.get<deInt32>();
1034 m_ctx.vertexAttribI4i(loc, attr.x(), attr.y(), attr.z(), attr.w());
1037 case DrawTestSpec::INPUTTYPE_UNSIGNED_INT:
1039 tcu::UVec4 attr = m_defaultAttrib.get<deUint32>();
1040 m_ctx.vertexAttribI4ui(loc, attr.x(), attr.y(), attr.z(), attr.w());
1044 DE_ASSERT(DE_FALSE);
1050 const deUint8* basePtr = DE_NULL;
1052 if (m_storage == DrawTestSpec::STORAGE_BUFFER)
1054 m_ctx.bindBuffer(targetToGL(m_target), m_glBuffer);
1055 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
1059 else if (m_storage == DrawTestSpec::STORAGE_USER)
1061 m_ctx.bindBuffer(targetToGL(m_target), 0);
1062 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
1064 basePtr = (const deUint8*)m_data;
1067 DE_ASSERT(DE_FALSE);
1069 if (!inputTypeIsFloatType(m_inputType))
1071 // Input is not float type
1073 if (outputTypeIsFloatType(m_outputType))
1075 const int size = (m_bgraOrder) ? (GL_BGRA) : (m_componentCount);
1077 DE_ASSERT(!(m_bgraOrder && m_componentCount != 4));
1079 // Output type is float type
1080 m_ctx.vertexAttribPointer(loc, size, inputTypeToGL(m_inputType), m_normalize, m_stride, basePtr + m_offset);
1081 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
1085 // Output type is int type
1086 m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, basePtr + m_offset);
1087 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()");
1092 // Input type is float type
1094 // Output type must be float type
1095 DE_ASSERT(outputTypeIsFloatType(m_outputType));
1097 m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, basePtr + m_offset);
1098 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
1101 if (m_instanceDivisor)
1102 m_ctx.vertexAttribDivisor(loc, m_instanceDivisor);
1106 void AttributeArray::bindIndexArray (DrawTestSpec::Target target)
1108 if (m_storage == DrawTestSpec::STORAGE_USER)
1111 else if (m_storage == DrawTestSpec::STORAGE_BUFFER)
1113 m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
1117 // DrawTestShaderProgram
1119 class DrawTestShaderProgram : public sglr::ShaderProgram
1122 DrawTestShaderProgram (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays);
1124 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
1125 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
1128 static std::string genVertexSource (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays);
1129 static std::string genFragmentSource (const glu::RenderContext& ctx);
1130 static void generateShaderParams (std::map<std::string, std::string>& params, glu::ContextType type);
1131 static rr::GenericVecType mapOutputType (const DrawTestSpec::OutputType& type);
1132 static int getComponentCount (const DrawTestSpec::OutputType& type);
1134 static sglr::pdec::ShaderProgramDeclaration createProgramDeclaration (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays);
1136 std::vector<int> m_componentCount;
1137 std::vector<bool> m_isCoord;
1138 std::vector<rr::GenericVecType> m_attrType;
1141 DrawTestShaderProgram::DrawTestShaderProgram (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays)
1142 : sglr::ShaderProgram (createProgramDeclaration(ctx, arrays))
1143 , m_componentCount (arrays.size())
1144 , m_isCoord (arrays.size())
1145 , m_attrType (arrays.size())
1147 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1149 m_componentCount[arrayNdx] = getComponentCount(arrays[arrayNdx]->getOutputType());
1150 m_isCoord[arrayNdx] = arrays[arrayNdx]->isPositionAttribute();
1151 m_attrType[arrayNdx] = mapOutputType(arrays[arrayNdx]->getOutputType());
1155 template <typename T>
1156 void calcShaderColorCoord (tcu::Vec2& coord, tcu::Vec3& color, const tcu::Vector<T, 4>& attribValue, bool isCoordinate, int numComponents)
1159 switch (numComponents)
1161 case 1: coord += tcu::Vec2((float)attribValue.x(), (float)attribValue.x()); break;
1162 case 2: coord += tcu::Vec2((float)attribValue.x(), (float)attribValue.y()); break;
1163 case 3: coord += tcu::Vec2((float)attribValue.x() + (float)attribValue.z(), (float)attribValue.y()); break;
1164 case 4: coord += tcu::Vec2((float)attribValue.x() + (float)attribValue.z(), (float)attribValue.y() + (float)attribValue.w()); break;
1171 switch (numComponents)
1174 color = color * (float)attribValue.x();
1178 color.x() = color.x() * (float)attribValue.x();
1179 color.y() = color.y() * (float)attribValue.y();
1183 color.x() = color.x() * (float)attribValue.x();
1184 color.y() = color.y() * (float)attribValue.y();
1185 color.z() = color.z() * (float)attribValue.z();
1189 color.x() = color.x() * (float)attribValue.x() * (float)attribValue.w();
1190 color.y() = color.y() * (float)attribValue.y() * (float)attribValue.w();
1191 color.z() = color.z() * (float)attribValue.z() * (float)attribValue.w();
1200 void DrawTestShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
1202 const float u_coordScale = getUniformByName("u_coordScale").value.f;
1203 const float u_colorScale = getUniformByName("u_colorScale").value.f;
1205 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1207 const size_t varyingLocColor = 0;
1209 rr::VertexPacket& packet = *packets[packetNdx];
1211 // Calc output color
1212 tcu::Vec2 coord = tcu::Vec2(0.0, 0.0);
1213 tcu::Vec3 color = tcu::Vec3(1.0, 1.0, 1.0);
1215 for (int attribNdx = 0; attribNdx < (int)m_attrType.size(); attribNdx++)
1217 const int numComponents = m_componentCount[attribNdx];
1218 const bool isCoord = m_isCoord[attribNdx];
1220 switch (m_attrType[attribNdx])
1222 case rr::GENERICVECTYPE_FLOAT: calcShaderColorCoord(coord, color, rr::readVertexAttribFloat(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), isCoord, numComponents); break;
1223 case rr::GENERICVECTYPE_INT32: calcShaderColorCoord(coord, color, rr::readVertexAttribInt (inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), isCoord, numComponents); break;
1224 case rr::GENERICVECTYPE_UINT32: calcShaderColorCoord(coord, color, rr::readVertexAttribUint (inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), isCoord, numComponents); break;
1230 // Transform position
1232 packet.position = tcu::Vec4(u_coordScale * coord.x(), u_coordScale * coord.y(), 1.0f, 1.0f);
1233 packet.pointSize = 1.0f;
1238 packet.outputs[varyingLocColor] = tcu::Vec4(u_colorScale * color.x(), u_colorScale * color.y(), u_colorScale * color.z(), 1.0f) * 0.5f + tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
1243 void DrawTestShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
1245 const size_t varyingLocColor = 0;
1247 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1249 rr::FragmentPacket& packet = packets[packetNdx];
1251 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
1252 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, varyingLocColor, fragNdx));
1256 std::string DrawTestShaderProgram::genVertexSource (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays)
1258 std::map<std::string, std::string> params;
1259 std::stringstream vertexShaderTmpl;
1261 generateShaderParams(params, ctx.getType());
1263 vertexShaderTmpl << "${VTX_HDR}";
1265 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1268 << "${VTX_IN} highp " << outputTypeToGLType(arrays[arrayNdx]->getOutputType()) << " a_" << arrayNdx << ";\n";
1272 "uniform highp float u_coordScale;\n"
1273 "uniform highp float u_colorScale;\n"
1274 "${VTX_OUT} ${COL_PRECISION} vec4 v_color;\n"
1277 "\tgl_PointSize = 1.0;\n"
1278 "\thighp vec2 coord = vec2(0.0, 0.0);\n"
1279 "\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n";
1281 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1283 const bool isPositionAttr = arrays[arrayNdx]->isPositionAttribute();
1287 switch (arrays[arrayNdx]->getOutputType())
1289 case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1290 case (DrawTestSpec::OUTPUTTYPE_INT):
1291 case (DrawTestSpec::OUTPUTTYPE_UINT):
1293 "\tcoord += vec2(float(a_" << arrayNdx << "), float(a_" << arrayNdx << "));\n";
1296 case (DrawTestSpec::OUTPUTTYPE_VEC2):
1297 case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1298 case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1300 "\tcoord += vec2(a_" << arrayNdx << ".xy);\n";
1303 case (DrawTestSpec::OUTPUTTYPE_VEC3):
1304 case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1305 case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1307 "\tcoord += vec2(a_" << arrayNdx << ".xy);\n"
1308 "\tcoord.x += float(a_" << arrayNdx << ".z);\n";
1311 case (DrawTestSpec::OUTPUTTYPE_VEC4):
1312 case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1313 case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1315 "\tcoord += vec2(a_" << arrayNdx << ".xy);\n"
1316 "\tcoord += vec2(a_" << arrayNdx << ".zw);\n";
1326 switch (arrays[arrayNdx]->getOutputType())
1328 case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1329 case (DrawTestSpec::OUTPUTTYPE_INT):
1330 case (DrawTestSpec::OUTPUTTYPE_UINT):
1332 "\tcolor = color * float(a_" << arrayNdx << ");\n";
1335 case (DrawTestSpec::OUTPUTTYPE_VEC2):
1336 case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1337 case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1339 "\tcolor.rg = color.rg * vec2(a_" << arrayNdx << ".xy);\n";
1342 case (DrawTestSpec::OUTPUTTYPE_VEC3):
1343 case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1344 case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1346 "\tcolor = color.rgb * vec3(a_" << arrayNdx << ".xyz);\n";
1349 case (DrawTestSpec::OUTPUTTYPE_VEC4):
1350 case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1351 case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1353 "\tcolor = color.rgb * vec3(a_" << arrayNdx << ".xyz) * float(a_" << arrayNdx << ".w);\n";
1364 "\tv_color = vec4(u_colorScale * color, 1.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);\n"
1365 "\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n"
1368 return tcu::StringTemplate(vertexShaderTmpl.str().c_str()).specialize(params);
1371 std::string DrawTestShaderProgram::genFragmentSource (const glu::RenderContext& ctx)
1373 std::map<std::string, std::string> params;
1375 generateShaderParams(params, ctx.getType());
1377 static const char* fragmentShaderTmpl =
1379 "${FRAG_IN} ${COL_PRECISION} vec4 v_color;\n"
1382 "\t${FRAG_COLOR} = v_color;\n"
1385 return tcu::StringTemplate(fragmentShaderTmpl).specialize(params);
1388 void DrawTestShaderProgram::generateShaderParams (std::map<std::string, std::string>& params, glu::ContextType type)
1390 if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_300_ES))
1392 params["VTX_IN"] = "in";
1393 params["VTX_OUT"] = "out";
1394 params["FRAG_IN"] = "in";
1395 params["FRAG_COLOR"] = "dEQP_FragColor";
1396 params["VTX_HDR"] = "#version 300 es\n";
1397 params["FRAG_HDR"] = "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1398 params["COL_PRECISION"] = "mediump";
1400 else if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_100_ES))
1402 params["VTX_IN"] = "attribute";
1403 params["VTX_OUT"] = "varying";
1404 params["FRAG_IN"] = "varying";
1405 params["FRAG_COLOR"] = "gl_FragColor";
1406 params["VTX_HDR"] = "";
1407 params["FRAG_HDR"] = "";
1408 params["COL_PRECISION"] = "mediump";
1410 else if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_430))
1412 params["VTX_IN"] = "in";
1413 params["VTX_OUT"] = "out";
1414 params["FRAG_IN"] = "in";
1415 params["FRAG_COLOR"] = "dEQP_FragColor";
1416 params["VTX_HDR"] = "#version 430\n";
1417 params["FRAG_HDR"] = "#version 430\nlayout(location = 0) out highp vec4 dEQP_FragColor;\n";
1418 params["COL_PRECISION"] = "highp";
1420 else if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_330))
1422 params["VTX_IN"] = "in";
1423 params["VTX_OUT"] = "out";
1424 params["FRAG_IN"] = "in";
1425 params["FRAG_COLOR"] = "dEQP_FragColor";
1426 params["VTX_HDR"] = "#version 330\n";
1427 params["FRAG_HDR"] = "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1428 params["COL_PRECISION"] = "mediump";
1431 DE_ASSERT(DE_FALSE);
1434 rr::GenericVecType DrawTestShaderProgram::mapOutputType (const DrawTestSpec::OutputType& type)
1438 case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1439 case (DrawTestSpec::OUTPUTTYPE_VEC2):
1440 case (DrawTestSpec::OUTPUTTYPE_VEC3):
1441 case (DrawTestSpec::OUTPUTTYPE_VEC4):
1442 return rr::GENERICVECTYPE_FLOAT;
1444 case (DrawTestSpec::OUTPUTTYPE_INT):
1445 case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1446 case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1447 case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1448 return rr::GENERICVECTYPE_INT32;
1450 case (DrawTestSpec::OUTPUTTYPE_UINT):
1451 case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1452 case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1453 case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1454 return rr::GENERICVECTYPE_UINT32;
1458 return rr::GENERICVECTYPE_LAST;
1462 int DrawTestShaderProgram::getComponentCount (const DrawTestSpec::OutputType& type)
1466 case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1467 case (DrawTestSpec::OUTPUTTYPE_INT):
1468 case (DrawTestSpec::OUTPUTTYPE_UINT):
1471 case (DrawTestSpec::OUTPUTTYPE_VEC2):
1472 case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1473 case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1476 case (DrawTestSpec::OUTPUTTYPE_VEC3):
1477 case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1478 case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1481 case (DrawTestSpec::OUTPUTTYPE_VEC4):
1482 case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1483 case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1492 sglr::pdec::ShaderProgramDeclaration DrawTestShaderProgram::createProgramDeclaration (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays)
1494 sglr::pdec::ShaderProgramDeclaration decl;
1496 for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1497 decl << sglr::pdec::VertexAttribute(std::string("a_") + de::toString(arrayNdx), mapOutputType(arrays[arrayNdx]->getOutputType()));
1499 decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
1500 decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
1502 decl << sglr::pdec::VertexSource(genVertexSource(ctx, arrays));
1503 decl << sglr::pdec::FragmentSource(genFragmentSource(ctx));
1505 decl << sglr::pdec::Uniform("u_coordScale", glu::TYPE_FLOAT);
1506 decl << sglr::pdec::Uniform("u_colorScale", glu::TYPE_FLOAT);
1511 class RandomArrayGenerator
1514 static char* generateArray (int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type);
1515 static char* generateIndices (int seed, int elementCount, DrawTestSpec::IndexType type, int offset, int min, int max, int indexBase);
1516 static rr::GenericVec4 generateAttributeValue (int seed, DrawTestSpec::InputType type);
1519 template<typename T>
1520 static char* createIndices (int seed, int elementCount, int offset, int min, int max, int indexBase);
1522 static char* generateBasicArray (int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type);
1523 template<typename T, typename GLType>
1524 static char* createBasicArray (int seed, int elementCount, int componentCount, int offset, int stride);
1525 static char* generatePackedArray (int seed, int elementCount, int componentCount, int offset, int stride);
1528 char* RandomArrayGenerator::generateArray (int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type)
1530 if (type == DrawTestSpec::INPUTTYPE_INT_2_10_10_10 || type == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
1531 return generatePackedArray(seed, elementCount, componentCount, offset, stride);
1533 return generateBasicArray(seed, elementCount, componentCount, offset, stride, type);
1536 char* RandomArrayGenerator::generateBasicArray (int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type)
1540 case DrawTestSpec::INPUTTYPE_FLOAT: return createBasicArray<float, GLValue::Float> (seed, elementCount, componentCount, offset, stride);
1541 case DrawTestSpec::INPUTTYPE_DOUBLE: return createBasicArray<double, GLValue::Double>(seed, elementCount, componentCount, offset, stride);
1542 case DrawTestSpec::INPUTTYPE_SHORT: return createBasicArray<deInt16, GLValue::Short> (seed, elementCount, componentCount, offset, stride);
1543 case DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT: return createBasicArray<deUint16, GLValue::Ushort>(seed, elementCount, componentCount, offset, stride);
1544 case DrawTestSpec::INPUTTYPE_BYTE: return createBasicArray<deInt8, GLValue::Byte> (seed, elementCount, componentCount, offset, stride);
1545 case DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE: return createBasicArray<deUint8, GLValue::Ubyte> (seed, elementCount, componentCount, offset, stride);
1546 case DrawTestSpec::INPUTTYPE_FIXED: return createBasicArray<deInt32, GLValue::Fixed> (seed, elementCount, componentCount, offset, stride);
1547 case DrawTestSpec::INPUTTYPE_INT: return createBasicArray<deInt32, GLValue::Int> (seed, elementCount, componentCount, offset, stride);
1548 case DrawTestSpec::INPUTTYPE_UNSIGNED_INT: return createBasicArray<deUint32, GLValue::Uint> (seed, elementCount, componentCount, offset, stride);
1549 case DrawTestSpec::INPUTTYPE_HALF: return createBasicArray<deFloat16, GLValue::Half> (seed, elementCount, componentCount, offset, stride);
1557 #if (DE_COMPILER == DE_COMPILER_GCC) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
1558 // GCC 4.8/4.9 incorrectly emits array-bounds warning from createBasicArray()
1559 # define GCC_ARRAY_BOUNDS_FALSE_NEGATIVE 1
1562 #if defined(GCC_ARRAY_BOUNDS_FALSE_NEGATIVE)
1563 # pragma GCC diagnostic push
1564 # pragma GCC diagnostic ignored "-Warray-bounds"
1567 template<typename T, typename GLType>
1568 char* RandomArrayGenerator::createBasicArray (int seed, int elementCount, int componentCount, int offset, int stride)
1570 DE_ASSERT(componentCount >= 1 && componentCount <= 4);
1572 const GLType min = extractGLValue<GLType>(GLValue::getMinValue(GLValueTypeTraits<GLType>::Type));
1573 const GLType max = extractGLValue<GLType>(GLValue::getMaxValue(GLValueTypeTraits<GLType>::Type));
1575 const size_t componentSize = sizeof(T);
1576 const size_t elementSize = componentSize * componentCount;
1577 const size_t bufferSize = offset + (elementCount - 1) * stride + elementSize;
1579 char* data = new char[bufferSize];
1580 char* writePtr = data + offset;
1582 GLType previousComponents[4];
1585 deRandom_init(&rnd, seed);
1587 for (int vertexNdx = 0; vertexNdx < elementCount; vertexNdx++)
1589 GLType components[4];
1591 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1593 components[componentNdx] = getRandom<GLType>(rnd, min, max);
1595 // Try to not create vertex near previous
1596 if (vertexNdx != 0 && abs(components[componentNdx] - previousComponents[componentNdx]) < minValue<GLType>())
1598 // Too close, try again (but only once)
1599 components[componentNdx] = getRandom<GLType>(rnd, min, max);
1603 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1604 previousComponents[componentNdx] = components[componentNdx];
1606 for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1607 alignmentSafeAssignment(writePtr + componentNdx*componentSize, components[componentNdx].getValue());
1615 #if defined(GCC_ARRAY_BOUNDS_FALSE_NEGATIVE)
1616 # pragma GCC diagnostic pop
1619 char* RandomArrayGenerator::generatePackedArray (int seed, int elementCount, int componentCount, int offset, int stride)
1621 DE_ASSERT(componentCount == 4);
1622 DE_UNREF(componentCount);
1624 const deUint32 limit10 = (1 << 10);
1625 const deUint32 limit2 = (1 << 2);
1626 const size_t elementSize = 4;
1627 const size_t bufferSize = offset + (elementCount - 1) * stride + elementSize;
1629 char* data = new char[bufferSize];
1630 char* writePtr = data + offset;
1633 deRandom_init(&rnd, seed);
1635 for (int vertexNdx = 0; vertexNdx < elementCount; vertexNdx++)
1637 const deUint32 x = deRandom_getUint32(&rnd) % limit10;
1638 const deUint32 y = deRandom_getUint32(&rnd) % limit10;
1639 const deUint32 z = deRandom_getUint32(&rnd) % limit10;
1640 const deUint32 w = deRandom_getUint32(&rnd) % limit2;
1641 const deUint32 packedValue = (w << 30) | (z << 20) | (y << 10) | (x);
1643 alignmentSafeAssignment(writePtr, packedValue);
1650 char* RandomArrayGenerator::generateIndices (int seed, int elementCount, DrawTestSpec::IndexType type, int offset, int min, int max, int indexBase)
1652 char* data = DE_NULL;
1656 case DrawTestSpec::INDEXTYPE_BYTE:
1657 data = createIndices<deUint8>(seed, elementCount, offset, min, max, indexBase);
1660 case DrawTestSpec::INDEXTYPE_SHORT:
1661 data = createIndices<deUint16>(seed, elementCount, offset, min, max, indexBase);
1664 case DrawTestSpec::INDEXTYPE_INT:
1665 data = createIndices<deUint32>(seed, elementCount, offset, min, max, indexBase);
1676 template<typename T>
1677 char* RandomArrayGenerator::createIndices (int seed, int elementCount, int offset, int min, int max, int indexBase)
1679 const size_t elementSize = sizeof(T);
1680 const size_t bufferSize = offset + elementCount * elementSize;
1682 char* data = new char[bufferSize];
1683 char* writePtr = data + offset;
1685 deUint32 oldNdx1 = deUint32(-1);
1686 deUint32 oldNdx2 = deUint32(-1);
1689 deRandom_init(&rnd, seed);
1691 DE_ASSERT(indexBase >= 0); // watch for underflows
1693 if (min < 0 || (size_t)min > std::numeric_limits<T>::max() ||
1694 max < 0 || (size_t)max > std::numeric_limits<T>::max() ||
1696 DE_FATAL("Invalid range");
1698 for (int elementNdx = 0; elementNdx < elementCount; ++elementNdx)
1700 deUint32 ndx = getRandom(rnd, GLValue::Uint::create(min), GLValue::Uint::create(max)).getValue();
1702 // Try not to generate same index as any of previous two. This prevents
1703 // generation of degenerate triangles and lines. If [min, max] is too
1704 // small this cannot be guaranteed.
1706 if (ndx == oldNdx1) ++ndx;
1707 if (ndx > (deUint32)max) ndx = min;
1708 if (ndx == oldNdx2) ++ndx;
1709 if (ndx > (deUint32)max) ndx = min;
1710 if (ndx == oldNdx1) ++ndx;
1711 if (ndx > (deUint32)max) ndx = min;
1718 alignmentSafeAssignment<T>(writePtr + elementSize * elementNdx, T(ndx));
1724 rr::GenericVec4 RandomArrayGenerator::generateAttributeValue (int seed, DrawTestSpec::InputType type)
1726 de::Random random(seed);
1730 case DrawTestSpec::INPUTTYPE_FLOAT:
1731 return rr::GenericVec4(generateRandomVec4(random));
1733 case DrawTestSpec::INPUTTYPE_INT:
1734 return rr::GenericVec4(generateRandomIVec4(random));
1736 case DrawTestSpec::INPUTTYPE_UNSIGNED_INT:
1737 return rr::GenericVec4(generateRandomUVec4(random));
1741 return rr::GenericVec4(tcu::Vec4(1, 1, 1, 1));
1753 AttributePack (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, sglr::Context& drawContext, const tcu::UVec2& screenSize, bool useVao, bool logEnabled);
1754 ~AttributePack (void);
1756 AttributeArray* getArray (int i);
1757 int getArrayCount (void);
1759 void newArray (DrawTestSpec::Storage storage);
1760 void clearArrays (void);
1761 void updateProgram (void);
1763 void render (DrawTestSpec::Primitive primitive, DrawTestSpec::DrawMethod drawMethod, int firstVertex, int vertexCount, DrawTestSpec::IndexType indexType, const void* indexOffset, int rangeStart, int rangeEnd, int instanceCount, int indirectOffset, int baseVertex, float coordScale, float colorScale, AttributeArray* indexArray);
1765 const tcu::Surface& getSurface (void) const { return m_screen; }
1767 tcu::TestContext& m_testCtx;
1768 glu::RenderContext& m_renderCtx;
1769 sglr::Context& m_ctx;
1771 std::vector<AttributeArray*>m_arrays;
1772 sglr::ShaderProgram* m_program;
1773 tcu::Surface m_screen;
1774 const bool m_useVao;
1775 const bool m_logEnabled;
1776 deUint32 m_programID;
1780 AttributePack::AttributePack (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, sglr::Context& drawContext, const tcu::UVec2& screenSize, bool useVao, bool logEnabled)
1781 : m_testCtx (testCtx)
1782 , m_renderCtx (renderCtx)
1783 , m_ctx (drawContext)
1784 , m_program (DE_NULL)
1785 , m_screen (screenSize.x(), screenSize.y())
1787 , m_logEnabled (logEnabled)
1792 m_ctx.genVertexArrays(1, &m_vaoID);
1795 AttributePack::~AttributePack (void)
1800 m_ctx.deleteProgram(m_programID);
1806 m_ctx.deleteVertexArrays(1, &m_vaoID);
1809 AttributeArray* AttributePack::getArray (int i)
1811 return m_arrays.at(i);
1814 int AttributePack::getArrayCount (void)
1816 return (int)m_arrays.size();
1819 void AttributePack::newArray (DrawTestSpec::Storage storage)
1821 m_arrays.push_back(new AttributeArray(storage, m_ctx));
1824 void AttributePack::clearArrays (void)
1826 for (std::vector<AttributeArray*>::iterator itr = m_arrays.begin(); itr != m_arrays.end(); itr++)
1831 void AttributePack::updateProgram (void)
1834 m_ctx.deleteProgram(m_programID);
1838 m_program = new DrawTestShaderProgram(m_renderCtx, m_arrays);
1839 m_programID = m_ctx.createProgram(m_program);
1842 void AttributePack::render (DrawTestSpec::Primitive primitive, DrawTestSpec::DrawMethod drawMethod, int firstVertex, int vertexCount, DrawTestSpec::IndexType indexType, const void* indexOffset, int rangeStart, int rangeEnd, int instanceCount, int indirectOffset, int baseVertex, float coordScale, float colorScale, AttributeArray* indexArray)
1844 DE_ASSERT(m_program != DE_NULL);
1845 DE_ASSERT(m_programID != 0);
1847 m_ctx.viewport(0, 0, m_screen.getWidth(), m_screen.getHeight());
1848 m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
1849 m_ctx.clear(GL_COLOR_BUFFER_BIT);
1851 m_ctx.useProgram(m_programID);
1852 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glUseProgram()");
1854 m_ctx.uniform1f(m_ctx.getUniformLocation(m_programID, "u_coordScale"), coordScale);
1855 m_ctx.uniform1f(m_ctx.getUniformLocation(m_programID, "u_colorScale"), colorScale);
1858 m_ctx.bindVertexArray(m_vaoID);
1861 indexArray->bindIndexArray(DrawTestSpec::TARGET_ELEMENT_ARRAY);
1863 for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
1865 std::stringstream attribName;
1866 attribName << "a_" << arrayNdx;
1868 deUint32 loc = m_ctx.getAttribLocation(m_programID, attribName.str().c_str());
1870 if (m_arrays[arrayNdx]->isBound())
1872 m_ctx.enableVertexAttribArray(loc);
1873 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glEnableVertexAttribArray()");
1876 m_arrays[arrayNdx]->bindAttribute(loc);
1879 if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWARRAYS)
1881 m_ctx.drawArrays(primitiveToGL(primitive), firstVertex, vertexCount);
1882 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArrays()");
1884 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED)
1886 m_ctx.drawArraysInstanced(primitiveToGL(primitive), firstVertex, vertexCount, instanceCount);
1887 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArraysInstanced()");
1889 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS)
1891 m_ctx.drawElements(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset);
1892 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElements()");
1894 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
1896 m_ctx.drawRangeElements(primitiveToGL(primitive), rangeStart, rangeEnd, vertexCount, indexTypeToGL(indexType), indexOffset);
1897 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawRangeElements()");
1899 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED)
1901 m_ctx.drawElementsInstanced(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset, instanceCount);
1902 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElementsInstanced()");
1904 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT)
1911 GLuint reservedMustBeZero;
1913 deUint8* buffer = new deUint8[sizeof(DrawCommand) + indirectOffset];
1916 DrawCommand command;
1918 command.count = vertexCount;
1919 command.primCount = instanceCount;
1920 command.first = firstVertex;
1921 command.reservedMustBeZero = 0;
1923 memcpy(buffer + indirectOffset, &command, sizeof(command));
1927 << tcu::TestLog::Message
1928 << "DrawArraysIndirectCommand:\n"
1929 << "\tcount: " << command.count << "\n"
1930 << "\tprimCount: " << command.primCount << "\n"
1931 << "\tfirst: " << command.first << "\n"
1932 << "\treservedMustBeZero: " << command.reservedMustBeZero << "\n"
1933 << tcu::TestLog::EndMessage;
1936 GLuint indirectBuf = 0;
1937 m_ctx.genBuffers(1, &indirectBuf);
1938 m_ctx.bindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuf);
1939 m_ctx.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand) + indirectOffset, buffer, GL_STATIC_DRAW);
1942 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "Setup draw indirect buffer");
1944 m_ctx.drawArraysIndirect(primitiveToGL(primitive), (const deInt8*)DE_NULL + indirectOffset);
1945 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArraysIndirect()");
1947 m_ctx.deleteBuffers(1, &indirectBuf);
1949 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT)
1957 GLuint reservedMustBeZero;
1959 deUint8* buffer = new deUint8[sizeof(DrawCommand) + indirectOffset];
1962 DrawCommand command;
1964 // index offset must be converted to firstIndex by dividing with the index element size
1965 DE_ASSERT(((const deUint8*)indexOffset - (const deUint8*)DE_NULL) % gls::DrawTestSpec::indexTypeSize(indexType) == 0); // \note This is checked in spec validation
1967 command.count = vertexCount;
1968 command.primCount = instanceCount;
1969 command.firstIndex = (glw::GLuint)(((const deUint8*)indexOffset - (const deUint8*)DE_NULL) / gls::DrawTestSpec::indexTypeSize(indexType));
1970 command.baseVertex = baseVertex;
1971 command.reservedMustBeZero = 0;
1973 memcpy(buffer + indirectOffset, &command, sizeof(command));
1977 << tcu::TestLog::Message
1978 << "DrawElementsIndirectCommand:\n"
1979 << "\tcount: " << command.count << "\n"
1980 << "\tprimCount: " << command.primCount << "\n"
1981 << "\tfirstIndex: " << command.firstIndex << "\n"
1982 << "\tbaseVertex: " << command.baseVertex << "\n"
1983 << "\treservedMustBeZero: " << command.reservedMustBeZero << "\n"
1984 << tcu::TestLog::EndMessage;
1987 GLuint indirectBuf = 0;
1988 m_ctx.genBuffers(1, &indirectBuf);
1989 m_ctx.bindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuf);
1990 m_ctx.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand) + indirectOffset, buffer, GL_STATIC_DRAW);
1993 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "Setup draw indirect buffer");
1995 m_ctx.drawElementsIndirect(primitiveToGL(primitive), indexTypeToGL(indexType), (const deInt8*)DE_NULL + indirectOffset);
1996 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArraysIndirect()");
1998 m_ctx.deleteBuffers(1, &indirectBuf);
2000 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
2002 m_ctx.drawElementsBaseVertex(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset, baseVertex);
2003 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElementsBaseVertex()");
2005 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX)
2007 m_ctx.drawElementsInstancedBaseVertex(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset, instanceCount, baseVertex);
2008 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElementsInstancedBaseVertex()");
2010 else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
2012 m_ctx.drawRangeElementsBaseVertex(primitiveToGL(primitive), rangeStart, rangeEnd, vertexCount, indexTypeToGL(indexType), indexOffset, baseVertex);
2013 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawRangeElementsBaseVertex()");
2016 DE_ASSERT(DE_FALSE);
2018 for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
2020 if (m_arrays[arrayNdx]->isBound())
2022 std::stringstream attribName;
2023 attribName << "a_" << arrayNdx;
2025 deUint32 loc = m_ctx.getAttribLocation(m_programID, attribName.str().c_str());
2027 m_ctx.disableVertexAttribArray(loc);
2028 GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDisableVertexAttribArray()");
2033 m_ctx.bindVertexArray(0);
2035 m_ctx.useProgram(0);
2036 m_ctx.readPixels(m_screen, 0, 0, m_screen.getWidth(), m_screen.getHeight());
2041 DrawTestSpec::AttributeSpec DrawTestSpec::AttributeSpec::createAttributeArray (InputType inputType, OutputType outputType, Storage storage, Usage usage, int componentCount, int offset, int stride, bool normalize, int instanceDivisor)
2043 DrawTestSpec::AttributeSpec spec;
2045 spec.inputType = inputType;
2046 spec.outputType = outputType;
2047 spec.storage = storage;
2049 spec.componentCount = componentCount;
2050 spec.offset = offset;
2051 spec.stride = stride;
2052 spec.normalize = normalize;
2053 spec.instanceDivisor = instanceDivisor;
2055 spec.useDefaultAttribute= false;
2060 DrawTestSpec::AttributeSpec DrawTestSpec::AttributeSpec::createDefaultAttribute (InputType inputType, OutputType outputType, int componentCount)
2062 DE_ASSERT(inputType == INPUTTYPE_INT || inputType == INPUTTYPE_UNSIGNED_INT || inputType == INPUTTYPE_FLOAT);
2063 DE_ASSERT(inputType == INPUTTYPE_FLOAT || componentCount == 4);
2065 DrawTestSpec::AttributeSpec spec;
2067 spec.inputType = inputType;
2068 spec.outputType = outputType;
2069 spec.storage = DrawTestSpec::STORAGE_LAST;
2070 spec.usage = DrawTestSpec::USAGE_LAST;
2071 spec.componentCount = componentCount;
2075 spec.instanceDivisor = 0;
2077 spec.useDefaultAttribute = true;
2082 DrawTestSpec::AttributeSpec::AttributeSpec (void)
2084 inputType = DrawTestSpec::INPUTTYPE_LAST;
2085 outputType = DrawTestSpec::OUTPUTTYPE_LAST;
2086 storage = DrawTestSpec::STORAGE_LAST;
2087 usage = DrawTestSpec::USAGE_LAST;
2092 instanceDivisor = 0;
2093 useDefaultAttribute = false;
2094 additionalPositionAttribute = false;
2095 bgraComponentOrder = false;
2098 int DrawTestSpec::AttributeSpec::hash (void) const
2100 if (useDefaultAttribute)
2102 return 1 * int(inputType) + 7 * int(outputType) + 13 * componentCount;
2106 return 1 * int(inputType) + 2 * int(outputType) + 3 * int(storage) + 5 * int(usage) + 7 * componentCount + 11 * offset + 13 * stride + 17 * (normalize ? 0 : 1) + 19 * instanceDivisor;
2110 bool DrawTestSpec::AttributeSpec::valid (glu::ApiType ctxType) const
2112 const bool inputTypeFloat = inputType == DrawTestSpec::INPUTTYPE_FLOAT || inputType == DrawTestSpec::INPUTTYPE_FIXED || inputType == DrawTestSpec::INPUTTYPE_HALF;
2113 const bool inputTypeUnsignedInteger = inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE || inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT || inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT || inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10;
2114 const bool inputTypeSignedInteger = inputType == DrawTestSpec::INPUTTYPE_BYTE || inputType == DrawTestSpec::INPUTTYPE_SHORT || inputType == DrawTestSpec::INPUTTYPE_INT || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2115 const bool inputTypePacked = inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2117 const bool outputTypeFloat = outputType == DrawTestSpec::OUTPUTTYPE_FLOAT || outputType == DrawTestSpec::OUTPUTTYPE_VEC2 || outputType == DrawTestSpec::OUTPUTTYPE_VEC3 || outputType == DrawTestSpec::OUTPUTTYPE_VEC4;
2118 const bool outputTypeSignedInteger = outputType == DrawTestSpec::OUTPUTTYPE_INT || outputType == DrawTestSpec::OUTPUTTYPE_IVEC2 || outputType == DrawTestSpec::OUTPUTTYPE_IVEC3 || outputType == DrawTestSpec::OUTPUTTYPE_IVEC4;
2119 const bool outputTypeUnsignedInteger = outputType == DrawTestSpec::OUTPUTTYPE_UINT || outputType == DrawTestSpec::OUTPUTTYPE_UVEC2 || outputType == DrawTestSpec::OUTPUTTYPE_UVEC3 || outputType == DrawTestSpec::OUTPUTTYPE_UVEC4;
2121 if (useDefaultAttribute)
2123 if (inputType != DrawTestSpec::INPUTTYPE_INT && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_INT && inputType != DrawTestSpec::INPUTTYPE_FLOAT)
2126 if (inputType != DrawTestSpec::INPUTTYPE_FLOAT && componentCount != 4)
2129 // no casting allowed (undefined results)
2130 if (inputType == DrawTestSpec::INPUTTYPE_INT && !outputTypeSignedInteger)
2132 if (inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT && !outputTypeUnsignedInteger)
2136 if (inputTypePacked && componentCount != 4)
2139 // Invalid conversions:
2142 if (inputTypeFloat && !outputTypeFloat)
2145 // uint -> int (undefined results)
2146 if (inputTypeUnsignedInteger && outputTypeSignedInteger)
2149 // int -> uint (undefined results)
2150 if (inputTypeSignedInteger && outputTypeUnsignedInteger)
2153 // packed -> non-float (packed formats are converted to floats)
2154 if (inputTypePacked && !outputTypeFloat)
2157 // Invalid normalize. Normalize is only valid if output type is float
2158 if (normalize && !outputTypeFloat)
2161 // Allow reverse order (GL_BGRA) only for packed and 4-component ubyte
2162 if (bgraComponentOrder && componentCount != 4)
2164 if (bgraComponentOrder && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 && inputType != DrawTestSpec::INPUTTYPE_INT_2_10_10_10 && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE)
2166 if (bgraComponentOrder && normalize != true)
2170 if (ctxType == glu::ApiType::es(2,0))
2172 if (inputType != DrawTestSpec::INPUTTYPE_FLOAT && inputType != DrawTestSpec::INPUTTYPE_FIXED &&
2173 inputType != DrawTestSpec::INPUTTYPE_BYTE && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE &&
2174 inputType != DrawTestSpec::INPUTTYPE_SHORT && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT)
2177 if (!outputTypeFloat)
2180 if (bgraComponentOrder)
2185 if (ctxType.getProfile() == glu::PROFILE_ES && ctxType.getMajorVersion() == 3)
2187 if (bgraComponentOrder)
2191 // No user pointers in GL core
2192 if (ctxType.getProfile() == glu::PROFILE_CORE)
2194 if (!useDefaultAttribute && storage == DrawTestSpec::STORAGE_USER)
2201 bool DrawTestSpec::AttributeSpec::isBufferAligned (void) const
2203 const bool inputTypePacked = inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2205 // Buffer alignment, offset is a multiple of underlying data type size?
2206 if (storage == STORAGE_BUFFER)
2208 int dataTypeSize = gls::DrawTestSpec::inputTypeSize(inputType);
2209 if (inputTypePacked)
2212 if (offset % dataTypeSize != 0)
2219 bool DrawTestSpec::AttributeSpec::isBufferStrideAligned (void) const
2221 const bool inputTypePacked = inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2223 // Buffer alignment, offset is a multiple of underlying data type size?
2224 if (storage == STORAGE_BUFFER)
2226 int dataTypeSize = gls::DrawTestSpec::inputTypeSize(inputType);
2227 if (inputTypePacked)
2230 if (stride % dataTypeSize != 0)
2237 std::string DrawTestSpec::targetToString(Target target)
2239 static const char* targets[] =
2241 "element_array", // TARGET_ELEMENT_ARRAY = 0,
2242 "array" // TARGET_ARRAY,
2245 return de::getSizedArrayElement<DrawTestSpec::TARGET_LAST>(targets, (int)target);
2248 std::string DrawTestSpec::inputTypeToString(InputType type)
2250 static const char* types[] =
2252 "float", // INPUTTYPE_FLOAT = 0,
2253 "fixed", // INPUTTYPE_FIXED,
2254 "double", // INPUTTYPE_DOUBLE
2256 "byte", // INPUTTYPE_BYTE,
2257 "short", // INPUTTYPE_SHORT,
2259 "unsigned_byte", // INPUTTYPE_UNSIGNED_BYTE,
2260 "unsigned_short", // INPUTTYPE_UNSIGNED_SHORT,
2262 "int", // INPUTTYPE_INT,
2263 "unsigned_int", // INPUTTYPE_UNSIGNED_INT,
2264 "half", // INPUTTYPE_HALF,
2265 "unsigned_int2_10_10_10", // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
2266 "int2_10_10_10" // INPUTTYPE_INT_2_10_10_10,
2269 return de::getSizedArrayElement<DrawTestSpec::INPUTTYPE_LAST>(types, (int)type);
2272 std::string DrawTestSpec::outputTypeToString(OutputType type)
2274 static const char* types[] =
2276 "float", // OUTPUTTYPE_FLOAT = 0,
2277 "vec2", // OUTPUTTYPE_VEC2,
2278 "vec3", // OUTPUTTYPE_VEC3,
2279 "vec4", // OUTPUTTYPE_VEC4,
2281 "int", // OUTPUTTYPE_INT,
2282 "uint", // OUTPUTTYPE_UINT,
2284 "ivec2", // OUTPUTTYPE_IVEC2,
2285 "ivec3", // OUTPUTTYPE_IVEC3,
2286 "ivec4", // OUTPUTTYPE_IVEC4,
2288 "uvec2", // OUTPUTTYPE_UVEC2,
2289 "uvec3", // OUTPUTTYPE_UVEC3,
2290 "uvec4", // OUTPUTTYPE_UVEC4,
2293 return de::getSizedArrayElement<DrawTestSpec::OUTPUTTYPE_LAST>(types, (int)type);
2296 std::string DrawTestSpec::usageTypeToString(Usage usage)
2298 static const char* usages[] =
2300 "dynamic_draw", // USAGE_DYNAMIC_DRAW = 0,
2301 "static_draw", // USAGE_STATIC_DRAW,
2302 "stream_draw", // USAGE_STREAM_DRAW,
2304 "stream_read", // USAGE_STREAM_READ,
2305 "stream_copy", // USAGE_STREAM_COPY,
2307 "static_read", // USAGE_STATIC_READ,
2308 "static_copy", // USAGE_STATIC_COPY,
2310 "dynamic_read", // USAGE_DYNAMIC_READ,
2311 "dynamic_copy", // USAGE_DYNAMIC_COPY,
2314 return de::getSizedArrayElement<DrawTestSpec::USAGE_LAST>(usages, (int)usage);
2317 std::string DrawTestSpec::storageToString (Storage storage)
2319 static const char* storages[] =
2321 "user_ptr", // STORAGE_USER = 0,
2322 "buffer" // STORAGE_BUFFER,
2325 return de::getSizedArrayElement<DrawTestSpec::STORAGE_LAST>(storages, (int)storage);
2328 std::string DrawTestSpec::primitiveToString (Primitive primitive)
2330 static const char* primitives[] =
2332 "points", // PRIMITIVE_POINTS ,
2333 "triangles", // PRIMITIVE_TRIANGLES,
2334 "triangle_fan", // PRIMITIVE_TRIANGLE_FAN,
2335 "triangle_strip", // PRIMITIVE_TRIANGLE_STRIP,
2336 "lines", // PRIMITIVE_LINES
2337 "line_strip", // PRIMITIVE_LINE_STRIP
2338 "line_loop", // PRIMITIVE_LINE_LOOP
2339 "lines_adjacency", // PRIMITIVE_LINES_ADJACENCY
2340 "line_strip_adjacency", // PRIMITIVE_LINE_STRIP_ADJACENCY
2341 "triangles_adjacency", // PRIMITIVE_TRIANGLES_ADJACENCY
2342 "triangle_strip_adjacency", // PRIMITIVE_TRIANGLE_STRIP_ADJACENCY
2345 return de::getSizedArrayElement<DrawTestSpec::PRIMITIVE_LAST>(primitives, (int)primitive);
2348 std::string DrawTestSpec::indexTypeToString (IndexType type)
2350 static const char* indexTypes[] =
2352 "byte", // INDEXTYPE_BYTE = 0,
2353 "short", // INDEXTYPE_SHORT,
2354 "int", // INDEXTYPE_INT,
2357 return de::getSizedArrayElement<DrawTestSpec::INDEXTYPE_LAST>(indexTypes, (int)type);
2360 std::string DrawTestSpec::drawMethodToString (DrawTestSpec::DrawMethod method)
2362 static const char* methods[] =
2364 "draw_arrays", //!< DRAWMETHOD_DRAWARRAYS
2365 "draw_arrays_instanced", //!< DRAWMETHOD_DRAWARRAYS_INSTANCED
2366 "draw_arrays_indirect", //!< DRAWMETHOD_DRAWARRAYS_INDIRECT
2367 "draw_elements", //!< DRAWMETHOD_DRAWELEMENTS
2368 "draw_range_elements", //!< DRAWMETHOD_DRAWELEMENTS_RANGED
2369 "draw_elements_instanced", //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED
2370 "draw_elements_indirect", //!< DRAWMETHOD_DRAWELEMENTS_INDIRECT
2371 "draw_elements_base_vertex", //!< DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
2372 "draw_elements_instanced_base_vertex", //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
2373 "draw_range_elements_base_vertex", //!< DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
2376 return de::getSizedArrayElement<DrawTestSpec::DRAWMETHOD_LAST>(methods, (int)method);
2379 int DrawTestSpec::inputTypeSize (InputType type)
2381 static const int size[] =
2383 (int)sizeof(float), // INPUTTYPE_FLOAT = 0,
2384 (int)sizeof(deInt32), // INPUTTYPE_FIXED,
2385 (int)sizeof(double), // INPUTTYPE_DOUBLE
2387 (int)sizeof(deInt8), // INPUTTYPE_BYTE,
2388 (int)sizeof(deInt16), // INPUTTYPE_SHORT,
2390 (int)sizeof(deUint8), // INPUTTYPE_UNSIGNED_BYTE,
2391 (int)sizeof(deUint16), // INPUTTYPE_UNSIGNED_SHORT,
2393 (int)sizeof(deInt32), // INPUTTYPE_INT,
2394 (int)sizeof(deUint32), // INPUTTYPE_UNSIGNED_INT,
2395 (int)sizeof(deFloat16), // INPUTTYPE_HALF,
2396 (int)sizeof(deUint32) / 4, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
2397 (int)sizeof(deUint32) / 4 // INPUTTYPE_INT_2_10_10_10,
2400 return de::getSizedArrayElement<DrawTestSpec::INPUTTYPE_LAST>(size, (int)type);
2403 int DrawTestSpec::indexTypeSize (IndexType type)
2405 static const int size[] =
2407 sizeof(deUint8), // INDEXTYPE_BYTE,
2408 sizeof(deUint16), // INDEXTYPE_SHORT,
2409 sizeof(deUint32), // INDEXTYPE_INT,
2412 return de::getSizedArrayElement<DrawTestSpec::INDEXTYPE_LAST>(size, (int)type);
2415 std::string DrawTestSpec::getName (void) const
2417 const MethodInfo methodInfo = getMethodInfo(drawMethod);
2418 const bool hasFirst = methodInfo.first;
2419 const bool instanced = methodInfo.instanced;
2420 const bool ranged = methodInfo.ranged;
2421 const bool indexed = methodInfo.indexed;
2423 std::stringstream name;
2425 for (size_t ndx = 0; ndx < attribs.size(); ++ndx)
2427 const AttributeSpec& attrib = attribs[ndx];
2429 if (attribs.size() > 1)
2430 name << "attrib" << ndx << "_";
2432 if (ndx == 0|| attrib.additionalPositionAttribute)
2437 if (attrib.useDefaultAttribute)
2441 << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << "_"
2442 << attrib.componentCount << "_"
2443 << DrawTestSpec::outputTypeToString(attrib.outputType) << "_";
2448 << DrawTestSpec::storageToString(attrib.storage) << "_"
2449 << attrib.offset << "_"
2450 << attrib.stride << "_"
2451 << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType);
2452 if (attrib.inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 && attrib.inputType != DrawTestSpec::INPUTTYPE_INT_2_10_10_10)
2453 name << attrib.componentCount;
2456 << (attrib.normalize ? "normalized_" : "")
2457 << DrawTestSpec::outputTypeToString(attrib.outputType) << "_"
2458 << DrawTestSpec::usageTypeToString(attrib.usage) << "_"
2459 << attrib.instanceDivisor << "_";
2465 << "index_" << DrawTestSpec::indexTypeToString(indexType) << "_"
2466 << DrawTestSpec::storageToString(indexStorage) << "_"
2467 << "offset" << indexPointerOffset << "_";
2469 name << "first" << first << "_";
2471 name << "ranged_" << indexMin << "_" << indexMax << "_";
2473 name << "instances" << instanceCount << "_";
2477 case DrawTestSpec::PRIMITIVE_POINTS:
2480 case DrawTestSpec::PRIMITIVE_TRIANGLES:
2481 name << "triangles_";
2483 case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
2484 name << "triangle_fan_";
2486 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
2487 name << "triangle_strip_";
2489 case DrawTestSpec::PRIMITIVE_LINES:
2492 case DrawTestSpec::PRIMITIVE_LINE_STRIP:
2493 name << "line_strip_";
2495 case DrawTestSpec::PRIMITIVE_LINE_LOOP:
2496 name << "line_loop_";
2498 case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
2499 name << "line_adjancency";
2501 case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
2502 name << "line_strip_adjancency";
2504 case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
2505 name << "triangles_adjancency";
2507 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
2508 name << "triangle_strip_adjancency";
2515 name << primitiveCount;
2520 std::string DrawTestSpec::getDesc (void) const
2522 std::stringstream desc;
2524 for (size_t ndx = 0; ndx < attribs.size(); ++ndx)
2526 const AttributeSpec& attrib = attribs[ndx];
2528 if (attrib.useDefaultAttribute)
2531 << "Attribute " << ndx << ": default, " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position ,") : ("color ,"))
2532 << "input datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << ", "
2533 << "input component count " << attrib.componentCount << ", "
2534 << "used as " << DrawTestSpec::outputTypeToString(attrib.outputType) << ", ";
2539 << "Attribute " << ndx << ": " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position ,") : ("color ,"))
2540 << "Storage in " << DrawTestSpec::storageToString(attrib.storage) << ", "
2541 << "stride " << attrib.stride << ", "
2542 << "input datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << ", "
2543 << "input component count " << attrib.componentCount << ", "
2544 << (attrib.normalize ? "normalized, " : "")
2545 << "used as " << DrawTestSpec::outputTypeToString(attrib.outputType) << ", "
2546 << "instance divisor " << attrib.instanceDivisor << ", ";
2550 if (drawMethod == DRAWMETHOD_DRAWARRAYS)
2554 << "first " << first << ", ";
2556 else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INSTANCED)
2559 << "drawArraysInstanced(), "
2560 << "first " << first << ", "
2561 << "instance count " << instanceCount << ", ";
2563 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS)
2566 << "drawElements(), "
2567 << "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2568 << "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2569 << "index offset " << indexPointerOffset << ", ";
2571 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_RANGED)
2574 << "drawElementsRanged(), "
2575 << "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2576 << "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2577 << "index offset " << indexPointerOffset << ", "
2578 << "range start " << indexMin << ", "
2579 << "range end " << indexMax << ", ";
2581 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INSTANCED)
2584 << "drawElementsInstanced(), "
2585 << "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2586 << "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2587 << "index offset " << indexPointerOffset << ", "
2588 << "instance count " << instanceCount << ", ";
2590 else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INDIRECT)
2593 << "drawArraysIndirect(), "
2594 << "first " << first << ", "
2595 << "instance count " << instanceCount << ", "
2596 << "indirect offset " << indirectOffset << ", ";
2598 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INDIRECT)
2601 << "drawElementsIndirect(), "
2602 << "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2603 << "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2604 << "index offset " << indexPointerOffset << ", "
2605 << "instance count " << instanceCount << ", "
2606 << "indirect offset " << indirectOffset << ", "
2607 << "base vertex " << baseVertex << ", ";
2610 DE_ASSERT(DE_FALSE);
2612 desc << primitiveCount;
2616 case DrawTestSpec::PRIMITIVE_POINTS:
2619 case DrawTestSpec::PRIMITIVE_TRIANGLES:
2620 desc << "triangles";
2622 case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
2623 desc << "triangles (fan)";
2625 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
2626 desc << "triangles (strip)";
2628 case DrawTestSpec::PRIMITIVE_LINES:
2631 case DrawTestSpec::PRIMITIVE_LINE_STRIP:
2632 desc << "lines (strip)";
2634 case DrawTestSpec::PRIMITIVE_LINE_LOOP:
2635 desc << "lines (loop)";
2637 case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
2638 desc << "lines (adjancency)";
2640 case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
2641 desc << "lines (strip, adjancency)";
2643 case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
2644 desc << "triangles (adjancency)";
2646 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
2647 desc << "triangles (strip, adjancency)";
2657 std::string DrawTestSpec::getMultilineDesc (void) const
2659 std::stringstream desc;
2661 for (size_t ndx = 0; ndx < attribs.size(); ++ndx)
2663 const AttributeSpec& attrib = attribs[ndx];
2665 if (attrib.useDefaultAttribute)
2668 << "Attribute " << ndx << ": default, " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position\n") : ("color\n"))
2669 << "\tinput datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << "\n"
2670 << "\tinput component count " << attrib.componentCount << "\n"
2671 << "\tused as " << DrawTestSpec::outputTypeToString(attrib.outputType) << "\n";
2676 << "Attribute " << ndx << ": " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position\n") : ("color\n"))
2677 << "\tStorage in " << DrawTestSpec::storageToString(attrib.storage) << "\n"
2678 << "\tstride " << attrib.stride << "\n"
2679 << "\tinput datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << "\n"
2680 << "\tinput component count " << attrib.componentCount << "\n"
2681 << (attrib.normalize ? "\tnormalized\n" : "")
2682 << "\tused as " << DrawTestSpec::outputTypeToString(attrib.outputType) << "\n"
2683 << "\tinstance divisor " << attrib.instanceDivisor << "\n";
2687 if (drawMethod == DRAWMETHOD_DRAWARRAYS)
2691 << "\tfirst " << first << "\n";
2693 else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INSTANCED)
2696 << "drawArraysInstanced()\n"
2697 << "\tfirst " << first << "\n"
2698 << "\tinstance count " << instanceCount << "\n";
2700 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS)
2703 << "drawElements()\n"
2704 << "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2705 << "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2706 << "\tindex offset " << indexPointerOffset << "\n";
2708 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_RANGED)
2711 << "drawElementsRanged()\n"
2712 << "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2713 << "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2714 << "\tindex offset " << indexPointerOffset << "\n"
2715 << "\trange start " << indexMin << "\n"
2716 << "\trange end " << indexMax << "\n";
2718 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INSTANCED)
2721 << "drawElementsInstanced()\n"
2722 << "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2723 << "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2724 << "\tindex offset " << indexPointerOffset << "\n"
2725 << "\tinstance count " << instanceCount << "\n";
2727 else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INDIRECT)
2730 << "drawArraysIndirect()\n"
2731 << "\tfirst " << first << "\n"
2732 << "\tinstance count " << instanceCount << "\n"
2733 << "\tindirect offset " << indirectOffset << "\n";
2735 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INDIRECT)
2738 << "drawElementsIndirect()\n"
2739 << "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2740 << "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2741 << "\tindex offset " << indexPointerOffset << "\n"
2742 << "\tinstance count " << instanceCount << "\n"
2743 << "\tindirect offset " << indirectOffset << "\n"
2744 << "\tbase vertex " << baseVertex << "\n";
2746 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
2749 << "drawElementsBaseVertex()\n"
2750 << "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2751 << "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2752 << "\tindex offset " << indexPointerOffset << "\n"
2753 << "\tbase vertex " << baseVertex << "\n";
2755 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX)
2758 << "drawElementsInstancedBaseVertex()\n"
2759 << "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2760 << "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2761 << "\tindex offset " << indexPointerOffset << "\n"
2762 << "\tinstance count " << instanceCount << "\n"
2763 << "\tbase vertex " << baseVertex << "\n";
2765 else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
2768 << "drawRangeElementsBaseVertex()\n"
2769 << "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2770 << "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2771 << "\tindex offset " << indexPointerOffset << "\n"
2772 << "\tbase vertex " << baseVertex << "\n"
2773 << "\trange start " << indexMin << "\n"
2774 << "\trange end " << indexMax << "\n";
2777 DE_ASSERT(DE_FALSE);
2779 desc << "\t" << primitiveCount << " ";
2783 case DrawTestSpec::PRIMITIVE_POINTS:
2786 case DrawTestSpec::PRIMITIVE_TRIANGLES:
2787 desc << "triangles";
2789 case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
2790 desc << "triangles (fan)";
2792 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
2793 desc << "triangles (strip)";
2795 case DrawTestSpec::PRIMITIVE_LINES:
2798 case DrawTestSpec::PRIMITIVE_LINE_STRIP:
2799 desc << "lines (strip)";
2801 case DrawTestSpec::PRIMITIVE_LINE_LOOP:
2802 desc << "lines (loop)";
2804 case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
2805 desc << "lines (adjancency)";
2807 case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
2808 desc << "lines (strip, adjancency)";
2810 case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
2811 desc << "triangles (adjancency)";
2813 case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
2814 desc << "triangles (strip, adjancency)";
2826 DrawTestSpec::DrawTestSpec (void)
2828 primitive = PRIMITIVE_LAST;
2830 drawMethod = DRAWMETHOD_LAST;
2831 indexType = INDEXTYPE_LAST;
2832 indexPointerOffset = 0;
2833 indexStorage = STORAGE_LAST;
2842 int DrawTestSpec::hash (void) const
2844 // Use only drawmode-relevant values in "hashing" as the unrelevant values might not be set (causing non-deterministic behavior).
2845 const MethodInfo methodInfo = getMethodInfo(drawMethod);
2846 const bool arrayed = methodInfo.first;
2847 const bool instanced = methodInfo.instanced;
2848 const bool ranged = methodInfo.ranged;
2849 const bool indexed = methodInfo.indexed;
2850 const bool indirect = methodInfo.indirect;
2851 const bool hasBaseVtx = methodInfo.baseVertex;
2853 const int indexHash = (!indexed) ? (0) : (int(indexType) + 10 * indexPointerOffset + 100 * int(indexStorage));
2854 const int arrayHash = (!arrayed) ? (0) : (first);
2855 const int indexRangeHash = (!ranged) ? (0) : (indexMin + 10 * indexMax);
2856 const int instanceHash = (!instanced) ? (0) : (instanceCount);
2857 const int indirectHash = (!indirect) ? (0) : (indirectOffset);
2858 const int baseVtxHash = (!hasBaseVtx) ? (0) : (baseVertex);
2859 const int basicHash = int(primitive) + 10 * primitiveCount + 100 * int(drawMethod);
2861 return indexHash + 3 * arrayHash + 5 * indexRangeHash + 7 * instanceHash + 13 * basicHash + 17 * (int)attribs.size() + 19 * primitiveCount + 23 * indirectHash + 27 * baseVtxHash;
2864 bool DrawTestSpec::valid (void) const
2866 DE_ASSERT(apiType.getProfile() != glu::PROFILE_LAST);
2867 DE_ASSERT(primitive != PRIMITIVE_LAST);
2868 DE_ASSERT(drawMethod != DRAWMETHOD_LAST);
2870 const MethodInfo methodInfo = getMethodInfo(drawMethod);
2872 for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2873 if (!attribs[ndx].valid(apiType))
2876 if (methodInfo.ranged)
2878 deUint32 maxIndexValue = 0;
2879 if (indexType == INDEXTYPE_BYTE)
2880 maxIndexValue = GLValue::getMaxValue(INPUTTYPE_UNSIGNED_BYTE).ub.getValue();
2881 else if (indexType == INDEXTYPE_SHORT)
2882 maxIndexValue = GLValue::getMaxValue(INPUTTYPE_UNSIGNED_SHORT).us.getValue();
2883 else if (indexType == INDEXTYPE_INT)
2884 maxIndexValue = GLValue::getMaxValue(INPUTTYPE_UNSIGNED_INT).ui.getValue();
2886 DE_ASSERT(DE_FALSE);
2888 if (indexMin > indexMax)
2890 if (indexMin < 0 || indexMax < 0)
2892 if ((deUint32)indexMin > maxIndexValue || (deUint32)indexMax > maxIndexValue)
2896 if (methodInfo.first && first < 0)
2900 if (apiType == glu::ApiType::es(2,0))
2902 if (drawMethod != gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS && drawMethod != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS)
2904 if (drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS && (indexType != INDEXTYPE_BYTE && indexType != INDEXTYPE_SHORT))
2908 // Indirect limitations
2909 if (methodInfo.indirect)
2911 // Indirect offset alignment
2912 if (indirectOffset % 4 != 0)
2915 // All attribute arrays must be stored in a buffer
2916 for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2917 if (!attribs[ndx].useDefaultAttribute && attribs[ndx].storage == gls::DrawTestSpec::STORAGE_USER)
2920 if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INDIRECT)
2922 // index offset must be convertable to firstIndex
2923 if (indexPointerOffset % gls::DrawTestSpec::indexTypeSize(indexType) != 0)
2926 // Indices must be in a buffer
2927 if (indexStorage != STORAGE_BUFFER)
2931 // Do not allow user pointer in GL core
2932 if (apiType.getProfile() == glu::PROFILE_CORE)
2934 if (methodInfo.indexed && indexStorage == DrawTestSpec::STORAGE_USER)
2941 DrawTestSpec::CompatibilityTestType DrawTestSpec::isCompatibilityTest (void) const
2943 const MethodInfo methodInfo = getMethodInfo(drawMethod);
2945 bool bufferAlignmentBad = false;
2946 bool strideAlignmentBad = false;
2948 // Attribute buffer alignment
2949 for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2950 if (!attribs[ndx].isBufferAligned())
2951 bufferAlignmentBad = true;
2953 // Attribute stride alignment
2954 for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2955 if (!attribs[ndx].isBufferStrideAligned())
2956 strideAlignmentBad = true;
2958 // Index buffer alignment
2959 if (methodInfo.indexed)
2961 if (indexStorage == STORAGE_BUFFER)
2964 if (indexType == INDEXTYPE_BYTE)
2966 else if (indexType == INDEXTYPE_SHORT)
2968 else if (indexType == INDEXTYPE_INT)
2971 DE_ASSERT(DE_FALSE);
2973 if (indexPointerOffset % indexSize != 0)
2974 bufferAlignmentBad = true;
2978 // \note combination bad alignment & stride is treated as bad offset
2979 if (bufferAlignmentBad)
2980 return COMPATIBILITY_UNALIGNED_OFFSET;
2981 else if (strideAlignmentBad)
2982 return COMPATIBILITY_UNALIGNED_STRIDE;
2984 return COMPATIBILITY_NONE;
2989 PRIMITIVECLASS_POINT = 0,
2990 PRIMITIVECLASS_LINE,
2991 PRIMITIVECLASS_TRIANGLE,
2996 static PrimitiveClass getDrawPrimitiveClass (gls::DrawTestSpec::Primitive primitiveType)
2998 switch (primitiveType)
3000 case gls::DrawTestSpec::PRIMITIVE_POINTS:
3001 return PRIMITIVECLASS_POINT;
3003 case gls::DrawTestSpec::PRIMITIVE_LINES:
3004 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP:
3005 case gls::DrawTestSpec::PRIMITIVE_LINE_LOOP:
3006 case gls::DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
3007 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
3008 return PRIMITIVECLASS_LINE;
3010 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES:
3011 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
3012 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
3013 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
3014 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
3015 return PRIMITIVECLASS_TRIANGLE;
3019 return PRIMITIVECLASS_LAST;
3023 static bool containsLineCases (const std::vector<DrawTestSpec>& m_specs)
3025 for (int ndx = 0; ndx < (int)m_specs.size(); ++ndx)
3027 if (getDrawPrimitiveClass(m_specs[ndx].primitive) == PRIMITIVECLASS_LINE)
3035 DrawTest::DrawTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const DrawTestSpec& spec, const char* name, const char* desc)
3036 : TestCase (testCtx, name, desc)
3037 , m_renderCtx (renderCtx)
3038 , m_contextInfo (DE_NULL)
3039 , m_refBuffers (DE_NULL)
3040 , m_refContext (DE_NULL)
3041 , m_glesContext (DE_NULL)
3042 , m_glArrayPack (DE_NULL)
3043 , m_rrArrayPack (DE_NULL)
3045 , m_maxDiffGreen (-1)
3046 , m_maxDiffBlue (-1)
3048 , m_result () // \note no per-iteration result logging (only one iteration)
3053 DrawTest::DrawTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc)
3054 : TestCase (testCtx, name, desc)
3055 , m_renderCtx (renderCtx)
3056 , m_contextInfo (DE_NULL)
3057 , m_refBuffers (DE_NULL)
3058 , m_refContext (DE_NULL)
3059 , m_glesContext (DE_NULL)
3060 , m_glArrayPack (DE_NULL)
3061 , m_rrArrayPack (DE_NULL)
3063 , m_maxDiffGreen (-1)
3064 , m_maxDiffBlue (-1)
3066 , m_result (testCtx.getLog(), "Iteration result: ")
3070 DrawTest::~DrawTest (void)
3075 void DrawTest::addIteration (const DrawTestSpec& spec, const char* description)
3078 const bool validSpec = spec.valid();
3079 DE_ASSERT(validSpec);
3084 // Check the context type is the same with other iterations
3085 if (!m_specs.empty())
3087 const bool validContext = m_specs[0].apiType == spec.apiType;
3088 DE_ASSERT(validContext);
3094 m_specs.push_back(spec);
3097 m_iteration_descriptions.push_back(std::string(description));
3099 m_iteration_descriptions.push_back(std::string());
3102 void DrawTest::init (void)
3104 DE_ASSERT(!m_specs.empty());
3105 DE_ASSERT(contextSupports(m_renderCtx.getType(), m_specs[0].apiType));
3107 const int renderTargetWidth = de::min(MAX_RENDER_TARGET_SIZE, m_renderCtx.getRenderTarget().getWidth());
3108 const int renderTargetHeight = de::min(MAX_RENDER_TARGET_SIZE, m_renderCtx.getRenderTarget().getHeight());
3110 // lines have significantly different rasterization in MSAA mode
3111 const bool isLineCase = containsLineCases(m_specs);
3112 const bool isMSAACase = m_renderCtx.getRenderTarget().getNumSamples() > 1;
3113 const int renderTargetSamples = (isMSAACase && isLineCase) ? (4) : (1);
3115 sglr::ReferenceContextLimits limits (m_renderCtx);
3116 bool useVao = false;
3118 m_glesContext = new sglr::GLContext(m_renderCtx, m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight));
3120 if (m_renderCtx.getType().getAPI() == glu::ApiType::es(2,0) || m_renderCtx.getType().getAPI() == glu::ApiType::es(3,0))
3122 else if (contextSupports(m_renderCtx.getType(), glu::ApiType::es(3,1)) || glu::isContextTypeGLCore(m_renderCtx.getType()))
3125 DE_FATAL("Unknown context type");
3127 m_refBuffers = new sglr::ReferenceContextBuffers(m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, renderTargetWidth, renderTargetHeight, renderTargetSamples);
3128 m_refContext = new sglr::ReferenceContext(limits, m_refBuffers->getColorbuffer(), m_refBuffers->getDepthbuffer(), m_refBuffers->getStencilbuffer());
3130 m_glArrayPack = new AttributePack(m_testCtx, m_renderCtx, *m_glesContext, tcu::UVec2(renderTargetWidth, renderTargetHeight), useVao, true);
3131 m_rrArrayPack = new AttributePack(m_testCtx, m_renderCtx, *m_refContext, tcu::UVec2(renderTargetWidth, renderTargetHeight), useVao, false);
3133 m_maxDiffRed = deCeilFloatToInt32(256.0f * (6.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().redBits)));
3134 m_maxDiffGreen = deCeilFloatToInt32(256.0f * (6.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().greenBits)));
3135 m_maxDiffBlue = deCeilFloatToInt32(256.0f * (6.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().blueBits)));
3136 m_contextInfo = glu::ContextInfo::create(m_renderCtx);
3139 void DrawTest::deinit (void)
3141 delete m_glArrayPack;
3142 delete m_rrArrayPack;
3143 delete m_refBuffers;
3144 delete m_refContext;
3145 delete m_glesContext;
3146 delete m_contextInfo;
3148 m_glArrayPack = DE_NULL;
3149 m_rrArrayPack = DE_NULL;
3150 m_refBuffers = DE_NULL;
3151 m_refContext = DE_NULL;
3152 m_glesContext = DE_NULL;
3153 m_contextInfo = DE_NULL;
3156 DrawTest::IterateResult DrawTest::iterate (void)
3158 const int specNdx = (m_iteration / 2);
3159 const DrawTestSpec& spec = m_specs[specNdx];
3161 if (spec.drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX ||
3162 spec.drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX ||
3163 spec.drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
3165 const bool supportsES32 = contextSupports(m_renderCtx.getType(), glu::ApiType::es(3, 2));
3166 TCU_CHECK_AND_THROW(NotSupportedError, supportsES32 || m_contextInfo->isExtensionSupported("GL_EXT_draw_elements_base_vertex"), "GL_EXT_draw_elements_base_vertex is not supported.");
3169 const bool drawStep = (m_iteration % 2) == 0;
3170 const bool compareStep = (m_iteration % 2) == 1;
3171 const IterateResult iterateResult = ((size_t)m_iteration + 1 == m_specs.size()*2) ? (STOP) : (CONTINUE);
3172 const bool updateProgram = (m_iteration == 0) || (drawStep && !checkSpecsShaderCompatible(m_specs[specNdx], m_specs[specNdx-1])); // try to use the same shader in all iterations
3173 IterationLogSectionEmitter sectionEmitter (m_testCtx.getLog(), specNdx, m_specs.size(), m_iteration_descriptions[specNdx], drawStep && m_specs.size()!=1);
3177 const MethodInfo methodInfo = getMethodInfo(spec.drawMethod);
3178 const bool indexed = methodInfo.indexed;
3179 const bool instanced = methodInfo.instanced;
3180 const bool ranged = methodInfo.ranged;
3181 const bool hasFirst = methodInfo.first;
3182 const bool hasBaseVtx = methodInfo.baseVertex;
3184 const size_t primitiveElementCount = getElementCount(spec.primitive, spec.primitiveCount); // !< elements to be drawn
3185 const int indexMin = (ranged) ? (spec.indexMin) : (0);
3186 const int firstAddition = (hasFirst) ? (spec.first) : (0);
3187 const int baseVertexAddition = (hasBaseVtx && spec.baseVertex > 0) ? ( spec.baseVertex) : (0); // spec.baseVertex > 0 => Create bigger attribute buffer
3188 const int indexBase = (hasBaseVtx && spec.baseVertex < 0) ? (-spec.baseVertex) : (0); // spec.baseVertex < 0 => Create bigger indices
3189 const size_t elementCount = primitiveElementCount + indexMin + firstAddition + baseVertexAddition; // !< elements in buffer (buffer should have at least primitiveElementCount ACCESSIBLE (index range, first) elements)
3190 const int maxElementIndex = (int)primitiveElementCount + indexMin + firstAddition - 1;
3191 const int indexMax = de::max(0, (ranged) ? (de::clamp<int>(spec.indexMax, 0, maxElementIndex)) : (maxElementIndex));
3192 float coordScale = getCoordScale(spec);
3193 float colorScale = getColorScale(spec);
3195 rr::GenericVec4 nullAttribValue;
3198 m_testCtx.getLog() << TestLog::Message << spec.getMultilineDesc() << TestLog::EndMessage;
3199 m_testCtx.getLog() << TestLog::Message << TestLog::EndMessage; // extra line for clarity
3203 m_glArrayPack->clearArrays();
3204 m_rrArrayPack->clearArrays();
3206 for (int attribNdx = 0; attribNdx < (int)spec.attribs.size(); attribNdx++)
3208 DrawTestSpec::AttributeSpec attribSpec = spec.attribs[attribNdx];
3209 const bool isPositionAttr = (attribNdx == 0) || (attribSpec.additionalPositionAttribute);
3211 if (attribSpec.useDefaultAttribute)
3213 const int seed = 10 * attribSpec.hash() + 100 * spec.hash() + attribNdx;
3214 rr::GenericVec4 attribValue = RandomArrayGenerator::generateAttributeValue(seed, attribSpec.inputType);
3216 m_glArrayPack->newArray(DrawTestSpec::STORAGE_USER);
3217 m_rrArrayPack->newArray(DrawTestSpec::STORAGE_USER);
3219 m_glArrayPack->getArray(attribNdx)->setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr, false);
3220 m_rrArrayPack->getArray(attribNdx)->setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr, false);
3224 const int seed = attribSpec.hash() + 100 * spec.hash() + attribNdx;
3225 const size_t elementSize = attribSpec.componentCount * DrawTestSpec::inputTypeSize(attribSpec.inputType);
3226 const size_t stride = (attribSpec.stride == 0) ? (elementSize) : (attribSpec.stride);
3227 const size_t evaluatedElementCount = (instanced && attribSpec.instanceDivisor > 0) ? (spec.instanceCount / attribSpec.instanceDivisor + 1) : (elementCount);
3228 const size_t referencedElementCount = (ranged) ? (de::max<size_t>(evaluatedElementCount, spec.indexMax + 1)) : (evaluatedElementCount);
3229 const size_t bufferSize = attribSpec.offset + stride * (referencedElementCount - 1) + elementSize;
3230 const char* data = RandomArrayGenerator::generateArray(seed, (int)referencedElementCount, attribSpec.componentCount, attribSpec.offset, (int)stride, attribSpec.inputType);
3234 m_glArrayPack->newArray(attribSpec.storage);
3235 m_rrArrayPack->newArray(attribSpec.storage);
3237 m_glArrayPack->getArray(attribNdx)->data(DrawTestSpec::TARGET_ARRAY, bufferSize, data, attribSpec.usage);
3238 m_rrArrayPack->getArray(attribNdx)->data(DrawTestSpec::TARGET_ARRAY, bufferSize, data, attribSpec.usage);
3240 m_glArrayPack->getArray(attribNdx)->setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr, attribSpec.bgraComponentOrder);
3241 m_rrArrayPack->getArray(attribNdx)->setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr, attribSpec.bgraComponentOrder);
3257 m_glArrayPack->updateProgram();
3258 m_rrArrayPack->updateProgram();
3267 const int seed = spec.hash();
3268 const size_t indexElementSize = DrawTestSpec::indexTypeSize(spec.indexType);
3269 const size_t indexArraySize = spec.indexPointerOffset + indexElementSize * elementCount;
3270 const char* indexArray = RandomArrayGenerator::generateIndices(seed, (int)elementCount, spec.indexType, spec.indexPointerOffset, indexMin, indexMax, indexBase);
3271 const char* indexPointerBase = (spec.indexStorage == DrawTestSpec::STORAGE_USER) ? (indexArray) : ((char*)DE_NULL);
3272 const char* indexPointer = indexPointerBase + spec.indexPointerOffset;
3274 de::UniquePtr<AttributeArray> glArray (new AttributeArray(spec.indexStorage, *m_glesContext));
3275 de::UniquePtr<AttributeArray> rrArray (new AttributeArray(spec.indexStorage, *m_refContext));
3279 glArray->data(DrawTestSpec::TARGET_ELEMENT_ARRAY, indexArraySize, indexArray, DrawTestSpec::USAGE_STATIC_DRAW);
3280 rrArray->data(DrawTestSpec::TARGET_ELEMENT_ARRAY, indexArraySize, indexArray, DrawTestSpec::USAGE_STATIC_DRAW);
3282 m_glArrayPack->render(spec.primitive, spec.drawMethod, 0, (int)primitiveElementCount, spec.indexType, indexPointer, spec.indexMin, spec.indexMax, spec.instanceCount, spec.indirectOffset, spec.baseVertex, coordScale, colorScale, glArray.get());
3283 m_rrArrayPack->render(spec.primitive, spec.drawMethod, 0, (int)primitiveElementCount, spec.indexType, indexPointer, spec.indexMin, spec.indexMax, spec.instanceCount, spec.indirectOffset, spec.baseVertex, coordScale, colorScale, rrArray.get());
3285 delete [] indexArray;
3290 delete [] indexArray;
3296 m_glArrayPack->render(spec.primitive, spec.drawMethod, spec.first, (int)primitiveElementCount, DrawTestSpec::INDEXTYPE_LAST, DE_NULL, 0, 0, spec.instanceCount, spec.indirectOffset, 0, coordScale, colorScale, DE_NULL);
3297 m_testCtx.touchWatchdog();
3298 m_rrArrayPack->render(spec.primitive, spec.drawMethod, spec.first, (int)primitiveElementCount, DrawTestSpec::INDEXTYPE_LAST, DE_NULL, 0, 0, spec.instanceCount, spec.indirectOffset, 0, coordScale, colorScale, DE_NULL);
3301 catch (glu::Error& err)
3303 // GL Errors are ok if the mode is not properly aligned
3305 const DrawTestSpec::CompatibilityTestType ctype = spec.isCompatibilityTest();
3307 m_testCtx.getLog() << TestLog::Message << "Got error: " << err.what() << TestLog::EndMessage;
3309 if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET)
3310 m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
3311 else if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
3312 m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
3317 else if (compareStep)
3319 if (!compare(spec.primitive))
3321 const DrawTestSpec::CompatibilityTestType ctype = spec.isCompatibilityTest();
3323 if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET)
3324 m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
3325 else if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
3326 m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
3328 m_result.addResult(QP_TEST_RESULT_FAIL, "Image comparison failed.");
3337 m_result.setTestContextResult(m_testCtx);
3340 return iterateResult;
3343 static bool isBlack (const tcu::RGBA& c)
3345 // ignore alpha channel
3346 return c.getRed() == 0 && c.getGreen() == 0 && c.getBlue() == 0;
3349 static bool isEdgeTripletComponent (int c1, int c2, int c3, int renderTargetDifference)
3351 const int roundingDifference = 2 * renderTargetDifference; // src and dst pixels rounded to different directions
3352 const int d1 = c2 - c1;
3353 const int d2 = c3 - c2;
3354 const int rampDiff = de::abs(d2 - d1);
3356 return rampDiff > roundingDifference;
3359 static bool isEdgeTriplet (const tcu::RGBA& c1, const tcu::RGBA& c2, const tcu::RGBA& c3, const tcu::IVec3& renderTargetThreshold)
3361 // black (background color) and non-black is always an edge
3363 const bool b1 = isBlack(c1);
3364 const bool b2 = isBlack(c2);
3365 const bool b3 = isBlack(c3);
3367 // both pixels with coverage and pixels without coverage
3368 if ((b1 && b2 && b3) == false && (b1 || b2 || b3) == true)
3373 // all with coverage
3374 DE_ASSERT(!b1 && !b2 && !b3);
3377 // Color is always linearly interpolated => component values change nearly linearly
3378 // in any constant direction on triangle hull. (df/dx ~= C).
3380 // Edge detection (this function) is run against the reference image
3381 // => no dithering to worry about
3383 return isEdgeTripletComponent(c1.getRed(), c2.getRed(), c3.getRed(), renderTargetThreshold.x()) ||
3384 isEdgeTripletComponent(c1.getGreen(), c2.getGreen(), c3.getGreen(), renderTargetThreshold.y()) ||
3385 isEdgeTripletComponent(c1.getBlue(), c2.getBlue(), c3.getBlue(), renderTargetThreshold.z());
3388 static bool pixelNearEdge (int x, int y, const tcu::Surface& ref, const tcu::IVec3& renderTargetThreshold)
3390 // should not be called for edge pixels
3391 DE_ASSERT(x >= 1 && x <= ref.getWidth()-2);
3392 DE_ASSERT(y >= 1 && y <= ref.getHeight()-2);
3396 for (int dy = -1; dy < 2; ++dy)
3398 const tcu::RGBA c1 = ref.getPixel(x-1, y+dy);
3399 const tcu::RGBA c2 = ref.getPixel(x, y+dy);
3400 const tcu::RGBA c3 = ref.getPixel(x+1, y+dy);
3401 if (isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
3407 for (int dx = -1; dx < 2; ++dx)
3409 const tcu::RGBA c1 = ref.getPixel(x+dx, y-1);
3410 const tcu::RGBA c2 = ref.getPixel(x+dx, y);
3411 const tcu::RGBA c3 = ref.getPixel(x+dx, y+1);
3412 if (isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
3419 static deUint32 getVisualizationGrayscaleColor (const tcu::RGBA& c)
3421 // make triangle coverage and error pixels obvious by converting coverage to grayscale
3425 return 50u + (deUint32)(c.getRed() + c.getBlue() + c.getGreen()) / 8u;
3428 static bool pixelNearLineIntersection (int x, int y, const tcu::Surface& target)
3430 // should not be called for edge pixels
3431 DE_ASSERT(x >= 1 && x <= target.getWidth()-2);
3432 DE_ASSERT(y >= 1 && y <= target.getHeight()-2);
3434 int coveredPixels = 0;
3436 for (int dy = -1; dy < 2; dy++)
3437 for (int dx = -1; dx < 2; dx++)
3439 const bool targetCoverage = !isBlack(target.getPixel(x+dx, y+dy));
3444 // A single thin line cannot have more than 3 covered pixels in a 3x3 area
3445 if (coveredPixels >= 4)
3453 static inline bool colorsEqual (const tcu::RGBA& colorA, const tcu::RGBA& colorB, const tcu::IVec3& compareThreshold)
3457 TCU_RGBA_RGB_MASK = tcu::RGBA::RED_MASK | tcu::RGBA::GREEN_MASK | tcu::RGBA::BLUE_MASK
3460 return tcu::compareThresholdMasked(colorA, colorB, tcu::RGBA(compareThreshold.x(), compareThreshold.y(), compareThreshold.z(), 0), TCU_RGBA_RGB_MASK);
3463 // search 3x3 are for matching color
3464 static bool pixelNeighborhoodContainsColor (const tcu::Surface& target, int x, int y, const tcu::RGBA& color, const tcu::IVec3& compareThreshold)
3466 // should not be called for edge pixels
3467 DE_ASSERT(x >= 1 && x <= target.getWidth()-2);
3468 DE_ASSERT(y >= 1 && y <= target.getHeight()-2);
3470 for (int dy = -1; dy < 2; dy++)
3471 for (int dx = -1; dx < 2; dx++)
3473 const tcu::RGBA targetCmpPixel = target.getPixel(x+dx, y+dy);
3474 if (colorsEqual(color, targetCmpPixel, compareThreshold))
3481 // search 3x3 are for matching coverage (coverage == (color != background color))
3482 static bool pixelNeighborhoodContainsCoverage (const tcu::Surface& target, int x, int y, bool coverage)
3484 // should not be called for edge pixels
3485 DE_ASSERT(x >= 1 && x <= target.getWidth()-2);
3486 DE_ASSERT(y >= 1 && y <= target.getHeight()-2);
3488 for (int dy = -1; dy < 2; dy++)
3489 for (int dx = -1; dx < 2; dx++)
3491 const bool targetCmpCoverage = !isBlack(target.getPixel(x+dx, y+dy));
3492 if (targetCmpCoverage == coverage)
3499 static bool edgeRelaxedImageCompare (tcu::TestLog& log, const char* imageSetName, const char* imageSetDesc, const tcu::Surface& reference, const tcu::Surface& result, const tcu::IVec3& compareThreshold, const tcu::IVec3& renderTargetThreshold, int maxAllowedInvalidPixels)
3501 DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
3503 const tcu::IVec4 green (0, 255, 0, 255);
3504 const tcu::IVec4 red (255, 0, 0, 255);
3505 const int width = reference.getWidth();
3506 const int height = reference.getHeight();
3507 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), width, height);
3508 const tcu::PixelBufferAccess errorAccess = errorMask.getAccess();
3509 int numFailingPixels = 0;
3511 // clear errormask edges which would otherwise be transparent
3513 tcu::clear(tcu::getSubregion(errorAccess, 0, 0, width, 1), green);
3514 tcu::clear(tcu::getSubregion(errorAccess, 0, height-1, width, 1), green);
3515 tcu::clear(tcu::getSubregion(errorAccess, 0, 0, 1, height), green);
3516 tcu::clear(tcu::getSubregion(errorAccess, width-1, 0, 1, height), green);
3518 // skip edge pixels since coverage on edge cannot be verified
3520 for (int y = 1; y < height - 1; ++y)
3521 for (int x = 1; x < width - 1; ++x)
3523 const tcu::RGBA refPixel = reference.getPixel(x, y);
3524 const tcu::RGBA screenPixel = result.getPixel(x, y);
3525 const bool directMatch = colorsEqual(refPixel, screenPixel, compareThreshold);
3526 const bool isOkReferencePixel = directMatch || pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
3527 const bool isOkScreenPixel = directMatch || pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
3529 if (isOkScreenPixel && isOkReferencePixel)
3531 // pixel valid, write greenish pixels to make the result image easier to read
3532 const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3533 errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3535 else if (!pixelNearEdge(x, y, reference, renderTargetThreshold))
3537 // non-edge pixel values must be within threshold of the reference values
3538 errorAccess.setPixel(red, x, y);
3543 // we are on/near an edge, verify only coverage (coverage == not background colored)
3544 const bool referenceCoverage = !isBlack(refPixel);
3545 const bool screenCoverage = !isBlack(screenPixel);
3546 const bool isOkReferenceCoverage = pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel
3547 const bool isOkScreenCoverage = pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel
3549 if (isOkScreenCoverage && isOkReferenceCoverage)
3551 // pixel valid, write greenish pixels to make the result image easier to read
3552 const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3553 errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3557 // coverage does not match
3558 errorAccess.setPixel(red, x, y);
3564 log << TestLog::Message
3565 << "Comparing images:\n"
3566 << "\tallowed deviation in pixel positions = 1\n"
3567 << "\tnumber of allowed invalid pixels = " << maxAllowedInvalidPixels << "\n"
3568 << "\tnumber of invalid pixels = " << numFailingPixels
3569 << TestLog::EndMessage;
3571 if (numFailingPixels > maxAllowedInvalidPixels)
3573 log << TestLog::Message
3574 << "Image comparison failed. Color threshold = (" << compareThreshold.x() << ", " << compareThreshold.y() << ", " << compareThreshold.z() << ")"
3575 << TestLog::EndMessage
3576 << TestLog::ImageSet(imageSetName, imageSetDesc)
3577 << TestLog::Image("Result", "Result", result)
3578 << TestLog::Image("Reference", "Reference", reference)
3579 << TestLog::Image("ErrorMask", "Error mask", errorMask)
3580 << TestLog::EndImageSet;
3586 log << TestLog::ImageSet(imageSetName, imageSetDesc)
3587 << TestLog::Image("Result", "Result", result)
3588 << TestLog::EndImageSet;
3594 static bool intersectionRelaxedLineImageCompare (tcu::TestLog& log, const char* imageSetName, const char* imageSetDesc, const tcu::Surface& reference, const tcu::Surface& result, const tcu::IVec3& compareThreshold, int maxAllowedInvalidPixels)
3596 DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
3598 const tcu::IVec4 green (0, 255, 0, 255);
3599 const tcu::IVec4 red (255, 0, 0, 255);
3600 const int width = reference.getWidth();
3601 const int height = reference.getHeight();
3602 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), width, height);
3603 const tcu::PixelBufferAccess errorAccess = errorMask.getAccess();
3604 int numFailingPixels = 0;
3606 // clear errormask edges which would otherwise be transparent
3608 tcu::clear(tcu::getSubregion(errorAccess, 0, 0, width, 1), green);
3609 tcu::clear(tcu::getSubregion(errorAccess, 0, height-1, width, 1), green);
3610 tcu::clear(tcu::getSubregion(errorAccess, 0, 0, 1, height), green);
3611 tcu::clear(tcu::getSubregion(errorAccess, width-1, 0, 1, height), green);
3613 // skip edge pixels since coverage on edge cannot be verified
3615 for (int y = 1; y < height - 1; ++y)
3616 for (int x = 1; x < width - 1; ++x)
3618 const tcu::RGBA refPixel = reference.getPixel(x, y);
3619 const tcu::RGBA screenPixel = result.getPixel(x, y);
3620 const bool directMatch = colorsEqual(refPixel, screenPixel, compareThreshold);
3621 const bool isOkScreenPixel = directMatch || pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold); // reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
3622 const bool isOkReferencePixel = directMatch || pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold); // screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
3624 if (isOkScreenPixel && isOkReferencePixel)
3626 // pixel valid, write greenish pixels to make the result image easier to read
3627 const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3628 errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3630 else if (!pixelNearLineIntersection(x, y, reference) &&
3631 !pixelNearLineIntersection(x, y, result))
3633 // non-intersection pixel values must be within threshold of the reference values
3634 errorAccess.setPixel(red, x, y);
3639 // pixel is near a line intersection
3640 // we are on/near an edge, verify only coverage (coverage == not background colored)
3641 const bool referenceCoverage = !isBlack(refPixel);
3642 const bool screenCoverage = !isBlack(screenPixel);
3643 const bool isOkScreenCoverage = pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage); // Check screen pixels against reference pixel
3644 const bool isOkReferenceCoverage = pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage); // Check reference pixel against screen pixel
3646 if (isOkScreenCoverage && isOkReferenceCoverage)
3648 // pixel valid, write greenish pixels to make the result image easier to read
3649 const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3650 errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3654 // coverage does not match
3655 errorAccess.setPixel(red, x, y);
3661 log << TestLog::Message
3662 << "Comparing images:\n"
3663 << "\tallowed deviation in pixel positions = 1\n"
3664 << "\tnumber of allowed invalid pixels = " << maxAllowedInvalidPixels << "\n"
3665 << "\tnumber of invalid pixels = " << numFailingPixels
3666 << TestLog::EndMessage;
3668 if (numFailingPixels > maxAllowedInvalidPixels)
3670 log << TestLog::Message
3671 << "Image comparison failed. Color threshold = (" << compareThreshold.x() << ", " << compareThreshold.y() << ", " << compareThreshold.z() << ")"
3672 << TestLog::EndMessage
3673 << TestLog::ImageSet(imageSetName, imageSetDesc)
3674 << TestLog::Image("Result", "Result", result)
3675 << TestLog::Image("Reference", "Reference", reference)
3676 << TestLog::Image("ErrorMask", "Error mask", errorMask)
3677 << TestLog::EndImageSet;
3683 log << TestLog::ImageSet(imageSetName, imageSetDesc)
3684 << TestLog::Image("Result", "Result", result)
3685 << TestLog::EndImageSet;
3691 bool DrawTest::compare (gls::DrawTestSpec::Primitive primitiveType)
3693 const tcu::Surface& ref = m_rrArrayPack->getSurface();
3694 const tcu::Surface& screen = m_glArrayPack->getSurface();
3696 if (m_renderCtx.getRenderTarget().getNumSamples() > 1)
3698 // \todo [mika] Improve compare when using multisampling
3699 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;
3700 return tcu::fuzzyCompare(m_testCtx.getLog(), "Compare Results", "Compare Results", ref.getAccess(), screen.getAccess(), 0.3f, tcu::COMPARE_LOG_RESULT);
3704 const PrimitiveClass primitiveClass = getDrawPrimitiveClass(primitiveType);
3705 const int maxAllowedInvalidPixelsWithPoints = 0; //!< points are unlikely to have overlapping fragments
3706 const int maxAllowedInvalidPixelsWithLines = 5; //!< line are allowed to have a few bad pixels
3707 const int maxAllowedInvalidPixelsWithTriangles = 10;
3709 switch (primitiveClass)
3711 case PRIMITIVECLASS_POINT:
3713 // Point are extremely unlikely to have overlapping regions, don't allow any no extra / missing pixels
3714 return tcu::intThresholdPositionDeviationErrorThresholdCompare(m_testCtx.getLog(),
3716 "Result of rendering",
3719 tcu::UVec4(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue, 256),
3720 tcu::IVec3(1, 1, 0), //!< 3x3 search kernel
3721 true, //!< relax comparison on the image boundary
3722 maxAllowedInvalidPixelsWithPoints, //!< error threshold
3723 tcu::COMPARE_LOG_RESULT);
3726 case PRIMITIVECLASS_LINE:
3728 // Lines can potentially have a large number of overlapping pixels. Pixel comparison may potentially produce
3729 // false negatives in such pixels if for example the pixel in question is overdrawn by another line in the
3730 // reference image but not in the resultin image. Relax comparison near line intersection points (areas) and
3731 // compare only coverage, not color, in such pixels
3732 return intersectionRelaxedLineImageCompare(m_testCtx.getLog(),
3734 "Result of rendering",
3737 tcu::IVec3(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue),
3738 maxAllowedInvalidPixelsWithLines);
3741 case PRIMITIVECLASS_TRIANGLE:
3743 // Triangles are likely to partially or fully overlap. Pixel difference comparison is fragile in pixels
3744 // where there could be potential overlapping since the pixels might be covered by one triangle in the
3745 // reference image and by the other in the result image. Relax comparsion near primitive edges and
3746 // compare only coverage, not color, in such pixels.
3747 const tcu::IVec3 renderTargetThreshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold().toIVec().xyz();
3749 return edgeRelaxedImageCompare(m_testCtx.getLog(),
3751 "Result of rendering",
3754 tcu::IVec3(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue),
3755 renderTargetThreshold,
3756 maxAllowedInvalidPixelsWithTriangles);
3766 float DrawTest::getCoordScale (const DrawTestSpec& spec) const
3768 float maxValue = 1.0f;
3770 for (int arrayNdx = 0; arrayNdx < (int)spec.attribs.size(); arrayNdx++)
3772 DrawTestSpec::AttributeSpec attribSpec = spec.attribs[arrayNdx];
3773 const bool isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
3774 float attrMaxValue = 0;
3776 if (!isPositionAttr)
3779 if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
3781 if (attribSpec.normalize)
3782 attrMaxValue += 1.0f;
3784 attrMaxValue += 1024.0f;
3786 else if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10)
3788 if (attribSpec.normalize)
3789 attrMaxValue += 1.0f;
3791 attrMaxValue += 512.0f;
3795 const float max = GLValue::getMaxValue(attribSpec.inputType).toFloat();
3797 attrMaxValue += (attribSpec.normalize && !inputTypeIsFloatType(attribSpec.inputType)) ? (1.0f) : (max * 1.1f);
3800 if (attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_VEC3 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_VEC4
3801 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_IVEC3 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_IVEC4
3802 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_UVEC3 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_UVEC4)
3805 maxValue += attrMaxValue;
3808 return 1.0f / maxValue;
3811 float DrawTest::getColorScale (const DrawTestSpec& spec) const
3813 float colorScale = 1.0f;
3815 for (int arrayNdx = 1; arrayNdx < (int)spec.attribs.size(); arrayNdx++)
3817 DrawTestSpec::AttributeSpec attribSpec = spec.attribs[arrayNdx];
3818 const bool isPositionAttr = (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
3823 if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
3825 if (!attribSpec.normalize)
3826 colorScale *= 1.0f / 1024.0f;
3828 else if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10)
3830 if (!attribSpec.normalize)
3831 colorScale *= 1.0f / 512.0f;
3835 const float max = GLValue::getMaxValue(attribSpec.inputType).toFloat();
3837 colorScale *= (attribSpec.normalize && !inputTypeIsFloatType(attribSpec.inputType) ? 1.0f : float(1.0 / double(max)));
3838 if (attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_VEC4 ||
3839 attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_UVEC4 ||
3840 attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_IVEC4)
3841 colorScale *= (attribSpec.normalize && !inputTypeIsFloatType(attribSpec.inputType) ? 1.0f : float(1.0 / double(max)));