13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.1 Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief gl_HelperInvocation tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es31fShaderHelperInvocationTests.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVector.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles31
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing glu::ShaderProgram;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::Vec2;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::IVec2;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::MovePtr;
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum PrimitiveType
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PRIMITIVETYPE_TRIANGLE = 0,
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PRIMITIVETYPE_LINE,
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PRIMITIVETYPE_WIDE_LINE,
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PRIMITIVETYPE_POINT,
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PRIMITIVETYPE_WIDE_POINT,
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	PRIMITIVETYPE_LAST
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNumVerticesPerPrimitive (PrimitiveType primType)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primType)
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_TRIANGLE:	return 3;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_LINE:		return 2;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_WIDE_LINE:	return 2;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_POINT:		return 1;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_WIDE_POINT:	return 1;
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic glu::PrimitiveType getGluPrimitiveType (PrimitiveType primType)
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (primType)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_TRIANGLE:	return glu::PRIMITIVETYPE_TRIANGLES;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_LINE:		return glu::PRIMITIVETYPE_LINES;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_WIDE_LINE:	return glu::PRIMITIVETYPE_LINES;
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_POINT:		return glu::PRIMITIVETYPE_POINTS;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_WIDE_POINT:	return glu::PRIMITIVETYPE_POINTS;
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return glu::PRIMITIVETYPE_LAST;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void genVertices (PrimitiveType primType, int numPrimitives, de::Random* rnd, vector<Vec2>* dst)
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
103566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const bool	isTri					= primType == PRIMITIVETYPE_TRIANGLE;
104566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const float	minCoord				= isTri ? -1.5f : -1.0f;
105566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const float	maxCoord				= isTri ? +1.5f : +1.0f;
106566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const int	numVerticesPerPrimitive	= getNumVerticesPerPrimitive(primType);
107566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const int	numVert					= numVerticesPerPrimitive*numPrimitives;
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst->resize(numVert);
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (size_t ndx = 0; ndx < dst->size(); ndx++)
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		(*dst)[ndx][0] = rnd->getFloat(minCoord, maxCoord);
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		(*dst)[ndx][1] = rnd->getFloat(minCoord, maxCoord);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
116566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry
117566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	// Don't produce completely or almost completely discardable primitives.
118566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	// \note: This doesn't guarantee that resulting primitives are visible or
119566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	//        produce any fragments. This just removes trivially discardable
120566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	//        primitives.
121566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	for (int primitiveNdx = 0; primitiveNdx < numPrimitives; ++primitiveNdx)
122566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	for (int component = 0; component < 2; ++component)
123566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	{
124566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		bool negativeClip = true;
125566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		bool positiveClip = true;
126566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry
127566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		for (int vertexNdx = 0; vertexNdx < numVerticesPerPrimitive; ++vertexNdx)
128566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		{
129566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			const float p = (*dst)[primitiveNdx * numVerticesPerPrimitive + vertexNdx][component];
130566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			// \note 0.9 instead of 1.0 to avoid just barely visible primitives
131566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			if (p > -0.9f)
132566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				negativeClip = false;
133566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			if (p < +0.9f)
134566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				positiveClip = false;
135566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		}
136566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry
137566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		// if discardable, just mirror first vertex along center
138566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		if (negativeClip || positiveClip)
139566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		{
140566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			(*dst)[primitiveNdx * numVerticesPerPrimitive + 0][0] *= -1.0f;
141566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			(*dst)[primitiveNdx * numVerticesPerPrimitive + 0][1] *= -1.0f;
142566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		}
143566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	}
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getInteger (const glw::Functions& gl, deUint32 pname)
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int v = 0;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getIntegerv(pname, &v);
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return v;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic Vec2 getRange (const glw::Functions& gl, deUint32 pname)
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Vec2 v(0.0f);
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.getFloatv(pname, v.getPtr());
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv()");
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return v;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void drawRandomPrimitives (const glu::RenderContext& renderCtx, deUint32 program, PrimitiveType primType, int numPrimitives, de::Random* rnd)
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl				= renderCtx.getFunctions();
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float						minPointSize	= 16.0f;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float						maxPointSize	= 32.0f;
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float						minLineWidth	= 16.0f;
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float						maxLineWidth	= 32.0f;
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<Vec2>					vertices;
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vector<glu::VertexArrayBinding>	vertexArrays;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	genVertices(primType, numPrimitives, rnd, &vertices);
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexArrays.push_back(glu::va::Float("a_position", 2, (int)vertices.size(), 0, (const float*)&vertices[0]));
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(program);
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Special state for certain primitives
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (primType == PRIMITIVETYPE_POINT || primType == PRIMITIVETYPE_WIDE_POINT)
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2		range			= getRange(gl, GL_ALIASED_POINT_SIZE_RANGE);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		isWidePoint		= primType == PRIMITIVETYPE_WIDE_POINT;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		pointSize		= isWidePoint ? de::min(rnd->getFloat(minPointSize, maxPointSize), range.y()) : 1.0f;
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		pointSizeLoc	= gl.getUniformLocation(program, "u_pointSize");
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(pointSizeLoc, pointSize);
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (primType == PRIMITIVETYPE_WIDE_LINE)
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const Vec2		range			= getRange(gl, GL_ALIASED_LINE_WIDTH_RANGE);
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		lineWidth		= de::min(rnd->getFloat(minLineWidth, maxLineWidth), range.y());
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.lineWidth(lineWidth);
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::draw(renderCtx, program, (int)vertexArrays.size(), &vertexArrays[0],
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  glu::PrimitiveList(getGluPrimitiveType(primType), (int)vertices.size()));
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass FboHelper
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								FboHelper			(const glu::RenderContext& renderCtx, int width, int height, deUint32 format, int numSamples);
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								~FboHelper			(void);
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						bindForRendering	(void);
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void						readPixels			(int x, int y, const tcu::PixelBufferAccess& dst);
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&	m_renderCtx;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					m_numSamples;
212566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const IVec2					m_size;
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Renderbuffer			m_colorbuffer;
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Framebuffer			m_framebuffer;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Renderbuffer			m_resolveColorbuffer;
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Framebuffer			m_resolveFramebuffer;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2203c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFboHelper::FboHelper (const glu::RenderContext& renderCtx, int width, int height, deUint32 format, int numSamples)
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_renderCtx			(renderCtx)
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numSamples			(numSamples)
223566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	, m_size				(width, height)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colorbuffer			(renderCtx)
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_framebuffer			(renderCtx)
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_resolveColorbuffer	(renderCtx)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_resolveFramebuffer	(renderCtx)
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl			= m_renderCtx.getFunctions();
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				maxSamples	= getInteger(gl, GL_MAX_SAMPLES);
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindRenderbuffer(GL_RENDERBUFFER, *m_colorbuffer);
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, format, width, height);
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, *m_framebuffer);
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *m_colorbuffer);
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (m_numSamples > maxSamples && gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Sample count exceeds GL_MAX_SAMPLES");
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_numSamples != 0)
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindRenderbuffer(GL_RENDERBUFFER, *m_resolveColorbuffer);
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindFramebuffer(GL_FRAMEBUFFER, *m_resolveFramebuffer);
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *m_resolveColorbuffer);
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create framebuffer");
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFboHelper::~FboHelper (void)
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FboHelper::bindForRendering (void)
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions& gl = m_renderCtx.getFunctions();
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindFramebuffer(GL_FRAMEBUFFER, *m_framebuffer);
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer()");
263566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	gl.viewport(0, 0, m_size.x(), m_size.y());
264566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	GLU_EXPECT_NO_ERROR(gl.getError(), "viewport()");
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FboHelper::readPixels (int x, int y, const tcu::PixelBufferAccess& dst)
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= m_renderCtx.getFunctions();
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				width	= dst.getWidth();
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				height	= dst.getHeight();
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_numSamples != 0)
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *m_resolveFramebuffer);
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.blitFramebuffer(x, y, width, height, x, y, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *m_resolveFramebuffer);
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::readPixels(m_renderCtx, x, y, dst);
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FRAMEBUFFER_WIDTH	= 256,
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FRAMEBUFFER_HEIGHT	= 256,
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FRAMEBUFFER_FORMAT	= GL_RGBA8,
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	NUM_SAMPLES_MAX		= -1
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies that gl_HelperInvocation is false in all rendered pixels.
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass HelperInvocationValueCase : public TestCase
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							HelperInvocationValueCase	(Context& context, const char* name, const char* description, PrimitiveType primType, int numSamples);
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~HelperInvocationValueCase	(void);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init						(void);
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit						(void);
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate						(void);
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const PrimitiveType		m_primitiveType;
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numSamples;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numIters;
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numPrimitivesPerIter;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ShaderProgram>	m_program;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<FboHelper>		m_fbo;
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_iterNdx;
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko PoyryHelperInvocationValueCase::HelperInvocationValueCase (Context& context, const char* name, const char* description, PrimitiveType primType, int numSamples)
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase					(context, name, description)
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_primitiveType			(primType)
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numSamples				(numSamples)
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numIters				(5)
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numPrimitivesPerIter	(10)
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterNdx					(0)
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryHelperInvocationValueCase::~HelperInvocationValueCase (void)
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid HelperInvocationValueCase::init (void)
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&	renderCtx		= m_context.getRenderContext();
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl				= renderCtx.getFunctions();
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					maxSamples		= getInteger(gl, GL_MAX_SAMPLES);
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					actualSamples	= m_numSamples == NUM_SAMPLES_MAX ? maxSamples : m_numSamples;
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = MovePtr<ShaderProgram>(new ShaderProgram(m_context.getRenderContext(),
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::ProgramSources()
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource(
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"#version 310 es\n"
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"in highp vec2 a_position;\n"
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"uniform highp float u_pointSize;\n"
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"void main (void)\n"
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"{\n"
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_PointSize = u_pointSize;\n"
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"}\n")
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource(
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"#version 310 es\n"
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"out mediump vec4 o_color;\n"
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"void main (void)\n"
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"{\n"
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	if (gl_HelperInvocation)\n"
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	else\n"
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"}\n")));
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_program.clear();
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Compile failed");
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << TestLog::Message << "Using GL_RGBA8 framebuffer with "
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   << actualSamples << " samples" << TestLog::EndMessage;
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo = MovePtr<FboHelper>(new FboHelper(renderCtx, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 FRAMEBUFFER_FORMAT, actualSamples));
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid HelperInvocationValueCase::deinit (void)
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo.clear();
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool verifyHelperInvocationValue (TestLog& log, const tcu::Surface& result, bool isMultiSample)
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		bgRef				(0, 0, 0, 255);
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		fgRef				(0, 255, 0, 255);
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		threshold			(1, isMultiSample ? 254 : 1, 1, 1);
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numInvalidPixels	= 0;
387566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	bool				renderedSomething	= false;
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < result.getHeight(); ++y)
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < result.getWidth(); ++x)
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::RGBA	resPix	= result.getPixel(x, y);
394566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			const bool		isBg	= tcu::compareThreshold(resPix, bgRef, threshold);
395566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			const bool		isFg	= tcu::compareThreshold(resPix, fgRef, threshold);
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
397566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			if (!isBg && !isFg)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numInvalidPixels += 1;
399566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry
400566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			if (isFg)
401566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				renderedSomething = true;
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numInvalidPixels > 0)
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Result", "Result image", result);
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Found " << numInvalidPixels << " invalid result pixels!" << TestLog::EndMessage;
409566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		return false;
410566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	}
411566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	else if (!renderedSomething)
412566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	{
413566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		log << TestLog::Image("Result", "Result image", result);
414566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		log << TestLog::Message << "ERROR: Result image was empty!" << TestLog::EndMessage;
415566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		return false;
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
418566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	{
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "All result pixels are valid" << TestLog::EndMessage;
420566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		return true;
421566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	}
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4243c827367444ee418f129b2c238299f49d3264554Jarkko PoyryHelperInvocationValueCase::IterateResult HelperInvocationValueCase::iterate (void)
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&		renderCtx	= m_context.getRenderContext();
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl			= renderCtx.getFunctions();
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string					sectionName	= string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(m_numIters);
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::ScopedLogSection		section		(m_testCtx.getLog(), (string("Iter") + de::toString(m_iterNdx)), sectionName);
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random						rnd			(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface					result		(FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo->bindForRendering();
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawRandomPrimitives(renderCtx, m_program->getProgram(), m_primitiveType, m_numPrimitivesPerIter, &rnd);
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo->readPixels(0, 0, result.getAccess());
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!verifyHelperInvocationValue(m_testCtx.getLog(), result, m_numSamples != 0))
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid pixels found");
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx += 1;
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Checks derivates when value depends on gl_HelperInvocation.
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass HelperInvocationDerivateCase : public TestCase
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
452566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry							HelperInvocationDerivateCase	(Context& context, const char* name, const char* description, PrimitiveType primType, int numSamples, const char* derivateFunc, bool checkAbsoluteValue);
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							~HelperInvocationDerivateCase	(void);
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					init							(void);
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					deinit							(void);
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult			iterate							(void);
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const PrimitiveType		m_primitiveType;
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numSamples;
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string		m_derivateFunc;
463566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const bool				m_checkAbsoluteValue;
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				m_numIters;
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<ShaderProgram>	m_program;
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MovePtr<FboHelper>		m_fbo;
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int						m_iterNdx;
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
472566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko PöyryHelperInvocationDerivateCase::HelperInvocationDerivateCase (Context& context, const char* name, const char* description, PrimitiveType primType, int numSamples, const char* derivateFunc, bool checkAbsoluteValue)
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase					(context, name, description)
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_primitiveType			(primType)
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numSamples				(numSamples)
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_derivateFunc			(derivateFunc)
477566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	, m_checkAbsoluteValue		(checkAbsoluteValue)
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numIters				(16)
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_iterNdx					(0)
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryHelperInvocationDerivateCase::~HelperInvocationDerivateCase (void)
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deinit();
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid HelperInvocationDerivateCase::init (void)
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&	renderCtx		= m_context.getRenderContext();
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl				= renderCtx.getFunctions();
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					maxSamples		= getInteger(gl, GL_MAX_SAMPLES);
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					actualSamples	= m_numSamples == NUM_SAMPLES_MAX ? maxSamples : m_numSamples;
494566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	const std::string			funcSource		= (m_checkAbsoluteValue) ? ("abs(" + m_derivateFunc + "(value))") : (m_derivateFunc + "(value)");
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program = MovePtr<ShaderProgram>(new ShaderProgram(m_context.getRenderContext(),
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::ProgramSources()
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::VertexSource(
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"#version 310 es\n"
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"in highp vec2 a_position;\n"
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"uniform highp float u_pointSize;\n"
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"void main (void)\n"
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"{\n"
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_Position = vec4(a_position, 0.0, 1.0);\n"
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	gl_PointSize = u_pointSize;\n"
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"}\n")
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< glu::FragmentSource(string(
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"#version 310 es\n"
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"out mediump vec4 o_color;\n"
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"void main (void)\n"
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"{\n"
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	highp float value		= gl_HelperInvocation ? 1.0 : 0.0;\n"
513566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				"	highp float derivate	= ") + funcSource + ";\n"
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	if (gl_HelperInvocation)\n"
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		o_color = vec4(1.0, 0.0, derivate, 1.0);\n"
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"	else\n"
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"		o_color = vec4(0.0, 1.0, derivate, 1.0);\n"
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				"}\n")));
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << *m_program;
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_program->isOk())
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_program.clear();
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Compile failed");
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << TestLog::Message << "Using GL_RGBA8 framebuffer with "
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   << actualSamples << " samples" << TestLog::EndMessage;
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo = MovePtr<FboHelper>(new FboHelper(renderCtx, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 FRAMEBUFFER_FORMAT, actualSamples));
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid HelperInvocationDerivateCase::deinit (void)
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_program.clear();
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo.clear();
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool hasNeighborWithColor (const tcu::Surface& surface, int x, int y, tcu::RGBA color, tcu::RGBA threshold)
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	w	= surface.getWidth();
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	h	= surface.getHeight();
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
548575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi	for (int dx = -1; dx < 2; dx++)
549575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi	for (int dy = -1; dy < 2; dy++)
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
551575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi		const IVec2	pos	= IVec2(x + dx, y + dy);
552575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi
553575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi		if (dx == 0 && dy == 0)
554575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi			continue;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (de::inBounds(pos.x(), 0, w) && de::inBounds(pos.y(), 0, h))
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::RGBA neighborColor = surface.getPixel(pos.x(), pos.y());
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (tcu::compareThreshold(color, neighborColor, threshold))
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return true;
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true; // Can't know for certain
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return false;
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool verifyHelperInvocationDerivate (TestLog& log, const tcu::Surface& result, bool isMultiSample)
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		bgRef				(0, 0, 0, 255);
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		fgRef				(0, 255, 0, 255);
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		isBgThreshold		(1, isMultiSample ? 254 : 1, 0, 1);
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::RGBA		isFgThreshold		(1, isMultiSample ? 254 : 1, 255, 1);
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numInvalidPixels	= 0;
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numNonZeroDeriv		= 0;
578566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	bool				renderedSomething	= false;
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < result.getHeight(); ++y)
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < result.getWidth(); ++x)
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::RGBA	resPix			= result.getPixel(x, y);
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isBg			= tcu::compareThreshold(resPix, bgRef, isBgThreshold);
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		isFg			= tcu::compareThreshold(resPix, fgRef, isFgThreshold);
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		nonZeroDeriv	= resPix.getBlue() > 0;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool		neighborBg		= nonZeroDeriv ? hasNeighborWithColor(result, x, y, bgRef, isBgThreshold) : false;
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (nonZeroDeriv)
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numNonZeroDeriv	+= 1;
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
593575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi			if ((!isBg && !isFg) ||							// Neither of valid colors (ignoring blue channel that has derivate)
594575313bd9b06b3be3c1eb1593d9f5b4adac80269Mika Isojärvi				(nonZeroDeriv && !neighborBg && !isFg))		// Has non-zero derivate, but sample not at primitive edge or inside primitive
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numInvalidPixels += 1;
596566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry
597566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry			if (isFg)
598566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				renderedSomething = true;
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
602566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	log << TestLog::Message << "Found " << numNonZeroDeriv << " pixels with non-zero derivate (neighbor sample has gl_HelperInvocation = true)" << TestLog::EndMessage;
603566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numInvalidPixels > 0)
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Result", "Result image", result);
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Found " << numInvalidPixels << " invalid result pixels!" << TestLog::EndMessage;
608566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		return false;
609566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	}
610566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	else if (!renderedSomething)
611566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	{
612566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		log << TestLog::Image("Result", "Result image", result);
613566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		log << TestLog::Message << "ERROR: Result image was empty!" << TestLog::EndMessage;
614566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		return false;
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
617566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	{
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "All result pixels are valid" << TestLog::EndMessage;
619566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry		return true;
620566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry	}
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6233c827367444ee418f129b2c238299f49d3264554Jarkko PoyryHelperInvocationDerivateCase::IterateResult HelperInvocationDerivateCase::iterate (void)
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::RenderContext&		renderCtx	= m_context.getRenderContext();
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&			gl			= renderCtx.getFunctions();
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const string					sectionName	= string("Iteration ") + de::toString(m_iterNdx+1) + " / " + de::toString(m_numIters);
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::ScopedLogSection		section		(m_testCtx.getLog(), (string("Iter") + de::toString(m_iterNdx)), sectionName);
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random						rnd			(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface					result		(FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo->bindForRendering();
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.clear(GL_COLOR_BUFFER_BIT);
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawRandomPrimitives(renderCtx, m_program->getProgram(), m_primitiveType, 1, &rnd);
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fbo->readPixels(0, 0, result.getAccess());
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!verifyHelperInvocationDerivate(m_testCtx.getLog(), result, m_numSamples != 0))
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid pixels found");
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_iterNdx += 1;
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6493c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderHelperInvocationTests::ShaderHelperInvocationTests (Context& context)
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "helper_invocation", "gl_HelperInvocation tests")
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6543c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderHelperInvocationTests::~ShaderHelperInvocationTests (void)
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderHelperInvocationTests::init (void)
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		caseName;
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		PrimitiveType	primType;
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_primTypes[] =
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "triangles",		PRIMITIVETYPE_TRIANGLE		},
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "lines",			PRIMITIVETYPE_LINE			},
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "wide_lines",		PRIMITIVETYPE_WIDE_LINE		},
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "points",			PRIMITIVETYPE_POINT			},
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "wide_points",	PRIMITIVETYPE_WIDE_POINT	}
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		suffix;
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				numSamples;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_sampleCounts[] =
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "",					0				},
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "_4_samples",			4				},
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "_8_samples",			8				},
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "_max_samples",		NUM_SAMPLES_MAX	}
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// value
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const valueGroup = new tcu::TestCaseGroup(m_testCtx, "value", "gl_HelperInvocation value in rendered pixels");
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(valueGroup);
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(s_sampleCounts); sampleCountNdx++)
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int primTypeNdx = 0; primTypeNdx < DE_LENGTH_OF_ARRAY(s_primTypes); primTypeNdx++)
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string		name		= string(s_primTypes[primTypeNdx].caseName) + s_sampleCounts[sampleCountNdx].suffix;
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const PrimitiveType	primType	= s_primTypes[primTypeNdx].primType;
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int			numSamples	= s_sampleCounts[sampleCountNdx].numSamples;
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				valueGroup->addChild(new HelperInvocationValueCase(m_context, name.c_str(), "", primType, numSamples));
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// derivate
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const derivateGroup = new tcu::TestCaseGroup(m_testCtx, "derivate", "Derivate of gl_HelperInvocation-dependent value");
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(derivateGroup);
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(s_sampleCounts); sampleCountNdx++)
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int primTypeNdx = 0; primTypeNdx < DE_LENGTH_OF_ARRAY(s_primTypes); primTypeNdx++)
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const string		name		= string(s_primTypes[primTypeNdx].caseName) + s_sampleCounts[sampleCountNdx].suffix;
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const PrimitiveType	primType	= s_primTypes[primTypeNdx].primType;
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int			numSamples	= s_sampleCounts[sampleCountNdx].numSamples;
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
716566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				derivateGroup->addChild(new HelperInvocationDerivateCase(m_context, (name + "_dfdx").c_str(),	"", primType, numSamples, "dFdx",	true));
717566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				derivateGroup->addChild(new HelperInvocationDerivateCase(m_context, (name + "_dfdy").c_str(),	"", primType, numSamples, "dFdy",	true));
718566182cb8143aef5be8210adb5819f3c6b5b5ea0Jarkko Pöyry				derivateGroup->addChild(new HelperInvocationDerivateCase(m_context, (name + "_fwidth").c_str(),	"", primType, numSamples, "fwidth",	false));
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles31
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
727