13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 3.0 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 Shader derivate function tests.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \todo [2013-06-25 pyry] Missing features:
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *  - lines and points
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *  - projected coordinates
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *  - continous non-trivial functions (sin, exp)
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *  - non-continous functions (step)
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "es3fShaderDerivateTests.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderProgram.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluPixelTransfer.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluShaderUtil.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluStrUtil.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTextureUtil.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluTexture.hpp"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuStringTemplate.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRenderTarget.hpp"
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuSurface.hpp"
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuRGBA.hpp"
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloat.hpp"
47bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry#include "tcuInterval.hpp"
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp"
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deString.h"
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsShaderRenderCase.hpp" // gls::setupDefaultUniforms()
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gles3
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace Functional
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::ostringstream;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VIEWPORT_WIDTH		= 167,
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VIEWPORT_HEIGHT		= 103,
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FBO_WIDTH			= 99,
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FBO_HEIGHT			= 133,
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MAX_FAILED_MESSAGES	= 10
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum DerivateFunc
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DERIVATE_DFDX	= 0,
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DERIVATE_DFDY,
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DERIVATE_FWIDTH,
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DERIVATE_LAST
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum SurfaceType
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SURFACETYPE_DEFAULT_FRAMEBUFFER = 0,
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SURFACETYPE_UNORM_FBO,
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SURFACETYPE_FLOAT_FBO,	// \note Uses RGBA32UI fbo actually, since FP rendertargets are not in core spec.
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SURFACETYPE_LAST
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Utilities
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AutoFbo
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AutoFbo (const glw::Functions& gl)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: m_gl	(gl)
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_fbo	(0)
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	~AutoFbo (void)
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_fbo)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_gl.deleteFramebuffers(1, &m_fbo);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void gen (void)
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!m_fbo);
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.genFramebuffers(1, &m_fbo);
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 operator* (void) const { return m_fbo; }
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	m_gl;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				m_fbo;
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass AutoRbo
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AutoRbo (const glw::Functions& gl)
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: m_gl	(gl)
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, m_rbo	(0)
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	~AutoRbo (void)
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_rbo)
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_gl.deleteRenderbuffers(1, &m_rbo);
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void gen (void)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!m_rbo);
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_gl.genRenderbuffers(1, &m_rbo);
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 operator* (void) const { return m_rbo; }
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	m_gl;
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32				m_rbo;
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getDerivateFuncName (DerivateFunc func)
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (func)
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DERIVATE_DFDX:		return "dFdx";
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DERIVATE_DFDY:		return "dFdy";
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DERIVATE_FWIDTH:	return "fwidth";
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const char* getDerivateFuncCaseName (DerivateFunc func)
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (func)
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DERIVATE_DFDX:		return "dfdx";
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DERIVATE_DFDY:		return "dfdy";
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DERIVATE_FWIDTH:	return "fwidth";
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::BVec4 getDerivateMask (glu::DataType type)
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT:		return tcu::BVec4(true, false, false, false);
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC2:	return tcu::BVec4(true, true, false, false);
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC3:	return tcu::BVec4(true, true, true, false);
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::TYPE_FLOAT_VEC4:	return tcu::BVec4(true, true, true, true);
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return tcu::BVec4(true);
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 readDerivate (const tcu::ConstPixelBufferAccess& surface, const tcu::Vec4& derivScale, const tcu::Vec4& derivBias, int x, int y)
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (surface.getPixel(x, y) - derivBias) / derivScale;
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::UVec4 getCompExpBits (const tcu::Vec4& v)
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::UVec4(tcu::Float32(v[0]).exponentBits(),
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  tcu::Float32(v[1]).exponentBits(),
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  tcu::Float32(v[2]).exponentBits(),
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					  tcu::Float32(v[3]).exponentBits());
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfloat computeFloatingPointError (const float value, const int numAccurateBits)
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numGarbageBits	= 23-numAccurateBits;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	mask			= (1u<<numGarbageBits)-1u;
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		exp				= tcu::Float32(value).exponent();
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Float32::construct(+1, exp, (1u<<23) | mask).asFloat() - tcu::Float32::construct(+1, exp, 1u<<23).asFloat();
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
222bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrystatic int getNumMantissaBits (const glu::Precision precision)
223bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
224bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	switch (precision)
225bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
226bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		case glu::PRECISION_HIGHP:		return 23;
227bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		case glu::PRECISION_MEDIUMP:	return 10;
228bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		case glu::PRECISION_LOWP:		return 6;
229bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		default:
230bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			DE_ASSERT(false);
231bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			return 0;
232bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
233bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
234bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
235bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrystatic int getMinExponent (const glu::Precision precision)
236bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
237bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	switch (precision)
238bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
239bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		case glu::PRECISION_HIGHP:		return -126;
240bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		case glu::PRECISION_MEDIUMP:	return -14;
241bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		case glu::PRECISION_LOWP:		return -8;
242bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		default:
243bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			DE_ASSERT(false);
244bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			return 0;
245bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
246bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
247bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
248bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrystatic float getSingleULPForExponent (int exp, int numMantissaBits)
249bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
250bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	if (numMantissaBits > 0)
251bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
252bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		DE_ASSERT(numMantissaBits <= 23);
253bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
254bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const int ulpBitNdx = 23-numMantissaBits;
255bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		return tcu::Float32::construct(+1, exp, (1<<23) | (1 << ulpBitNdx)).asFloat() - tcu::Float32::construct(+1, exp, (1<<23)).asFloat();
256bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
257bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	else
258bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
259bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		DE_ASSERT(numMantissaBits == 0);
260bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		return tcu::Float32::construct(+1, exp, (1<<23)).asFloat();
261bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
262bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
263bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
264bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrystatic float getSingleULPForValue (float value, int numMantissaBits)
265bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
266bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const int exp = tcu::Float32(value).exponent();
267bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	return getSingleULPForExponent(exp, numMantissaBits);
268bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
269bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
27059b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyrystatic float convertFloatFlushToZeroRtn (float value, int minExponent, int numAccurateBits)
271bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
272bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	if (value == 0.0f)
273bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
274bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		return 0.0f;
275bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
276bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	else
277bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
278bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const tcu::Float32	inputFloat			= tcu::Float32(value);
279bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const int			numTruncatedBits	= 23-numAccurateBits;
280bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const deUint32		truncMask			= (1u<<numTruncatedBits)-1u;
281bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
282bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		if (value > 0.0f)
283bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		{
284bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			if (value > 0.0f && tcu::Float32(value).exponent() < minExponent)
285bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			{
286bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				// flush to zero if possible
287bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				return 0.0f;
288bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			}
289bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			else
290bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			{
291bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				// just mask away non-representable bits
292bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				return tcu::Float32::construct(+1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).asFloat();
293bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			}
294bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		}
295bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		else
296bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		{
297bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			if (inputFloat.mantissa() & truncMask)
298bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			{
299bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				// decrement one ulp if truncated bits are non-zero (i.e. if value is not representable)
300bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				return tcu::Float32::construct(-1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).asFloat() - getSingleULPForExponent(inputFloat.exponent(), numAccurateBits);
301bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			}
302bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			else
303bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			{
304bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				// value is representable, no need to do anything
305bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				return value;
306bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			}
307bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		}
308bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
309bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
310bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
31159b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyrystatic float convertFloatFlushToZeroRtp (float value, int minExponent, int numAccurateBits)
312bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
31359b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry	return -convertFloatFlushToZeroRtn(-value, minExponent, numAccurateBits);
314bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
315bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
316bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrystatic float addErrorUlp (float value, float numUlps, int numMantissaBits)
317bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
318bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	return value + numUlps * getSingleULPForValue(value, numMantissaBits);
319bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
320bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
321bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyryenum
322bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
323bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	INTERPOLATION_LOST_BITS = 3, // number mantissa of bits allowed to be lost in varying interpolation
324bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry};
325bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 getDerivateThreshold (const glu::Precision precision, const tcu::Vec4& valueMin, const tcu::Vec4& valueMax, const tcu::Vec4& expectedDerivate)
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
328bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const int			baseBits		= getNumMantissaBits(precision);
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::UVec4	derivExp		= getCompExpBits(expectedDerivate);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::UVec4	maxValueExp		= max(getCompExpBits(valueMin), getCompExpBits(valueMax));
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::UVec4	numBitsLost		= maxValueExp - min(maxValueExp, derivExp);
332bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const tcu::IVec4	numAccurateBits	= max(baseBits - numBitsLost.asInt() - (int)INTERPOLATION_LOST_BITS, tcu::IVec4(0));
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Vec4(computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]),
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]),
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]),
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 computeFloatingPointError(expectedDerivate[3], numAccurateBits[3]));
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct LogVecComps
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4&	v;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numComps;
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	LogVecComps (const tcu::Vec4& v_, int numComps_)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: v			(v_)
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, numComps	(numComps_)
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const LogVecComps& v)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inRange(v.numComps, 1, 4));
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (v.numComps == 1)		return str << v.v[0];
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (v.numComps == 2)	return str << v.v.toWidth<2>();
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (v.numComps == 3)	return str << v.v.toWidth<3>();
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else						return str << v.v;
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
366bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyryenum VerificationLogging
367bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
368bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	LOG_ALL = 0,
369bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	LOG_NOTHING
370bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry};
371bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool verifyConstantDerivate (tcu::TestLog&						log,
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const tcu::ConstPixelBufferAccess&	result,
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const tcu::PixelBufferAccess&		errorMask,
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									glu::DataType						dataType,
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const tcu::Vec4&					reference,
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const tcu::Vec4&					threshold,
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									const tcu::Vec4&					scale,
379bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry									const tcu::Vec4&					bias,
380bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry									VerificationLogging					logPolicy = LOG_ALL)
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			numComps		= glu::getDataTypeFloatScalars(dataType);
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::BVec4	mask			= tcu::logicalNot(getDerivateMask(dataType));
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailedPixels	= 0;
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
386bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	if (logPolicy == LOG_ALL)
387bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		log << TestLog::Message << "Expecting " << LogVecComps(reference, numComps) << " with threshold " << LogVecComps(threshold, numComps) << TestLog::EndMessage;
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::Vec4		resDerivate		= readDerivate(result, scale, bias, x, y);
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const bool			isOk			= tcu::allEqual(tcu::logicalOr(tcu::lessThanEqual(tcu::abs(reference - resDerivate), threshold), mask), tcu::BVec4(true));
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!isOk)
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
398bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				if (numFailedPixels < MAX_FAILED_MESSAGES && logPolicy == LOG_ALL)
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "FAIL: got " << LogVecComps(resDerivate, numComps)
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< ", diff = " << LogVecComps(tcu::abs(reference - resDerivate), numComps)
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											<< ", at x = " << x << ", y = " << y
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						<< TestLog::EndMessage;
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailedPixels += 1;
404c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski				errorMask.setPixel(tcu::RGBA::red().toVec(), x, y);
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
409bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	if (numFailedPixels >= MAX_FAILED_MESSAGES && logPolicy == LOG_ALL)
410bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		log << TestLog::Message << "..." << TestLog::EndMessage;
411bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
412bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	if (numFailedPixels > 0 && logPolicy == LOG_ALL)
413bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage;
414bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
415bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	return numFailedPixels == 0;
416bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
417bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
418bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrystruct Linear2DFunctionEvaluator
419bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
420bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	tcu::Matrix<float, 4, 3> matrix;
421bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
422bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	//      .-----.
423bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	//      | s_x |
424bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	//  M x | s_y |
425bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	//      | 1.0 |
426bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	//      '-----'
427bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	tcu::Vec4 evaluateAt (float screenX, float screenY) const;
428bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry};
429bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
430bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrytcu::Vec4 Linear2DFunctionEvaluator::evaluateAt (float screenX, float screenY) const
431bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
432bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const tcu::Vec3 position(screenX, screenY, 1.0f);
433bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	return matrix * position;
434bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry}
435bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
436bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyrystatic bool reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog&							log,
437bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  const tcu::ConstPixelBufferAccess&	result,
438bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  const tcu::PixelBufferAccess&			errorMask,
439bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  glu::DataType							dataType,
440bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  glu::Precision						precision,
441bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  const tcu::Vec4&						derivScale,
442bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  const tcu::Vec4&						derivBias,
443bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  const tcu::Vec4&						surfaceThreshold,
444bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  DerivateFunc							derivateFunc,
445bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry														  const Linear2DFunctionEvaluator&		function)
446bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry{
447bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	DE_ASSERT(result.getWidth() == errorMask.getWidth());
448bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	DE_ASSERT(result.getHeight() == errorMask.getHeight());
449bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	DE_ASSERT(derivateFunc == DERIVATE_DFDX || derivateFunc == DERIVATE_DFDY);
450bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
451bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const tcu::IVec4	red						(255, 0, 0, 255);
452bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const tcu::IVec4	green					(0, 255, 0, 255);
453bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const float			divisionErrorUlps		= 2.5f;
454bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
455bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const int			numComponents			= glu::getDataTypeFloatScalars(dataType);
456bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const int			numBits					= getNumMantissaBits(precision);
457bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const int			minExponent				= getMinExponent(precision);
458bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
459bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	const int			numVaryingSampleBits	= numBits - INTERPOLATION_LOST_BITS;
460bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	int					numFailedPixels			= 0;
461bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
462bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	tcu::clear(errorMask, green);
463bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
464bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	// search for failed pixels
465bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	for (int y = 0; y < result.getHeight(); ++y)
466bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	for (int x = 0; x < result.getWidth(); ++x)
467bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
468bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		//                 flushToZero?(f2z?(functionValueCurrent) - f2z?(functionValueBefore))
469bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// flushToZero? ( ------------------------------------------------------------------------ +- 2.5 ULP )
470bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		//                                                  dx
471bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
472bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const tcu::Vec4	resultDerivative		= readDerivate(result, derivScale, derivBias, x, y);
473bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
474bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// sample at the front of the back pixel and the back of the front pixel to cover the whole area of
475bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// legal sample positions. In general case this is NOT OK, but we know that the target funtion is
476bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// (mostly*) linear which allows us to take the sample points at arbitrary points. This gets us the
477bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// maximum difference possible in exponents which are used in error bound calculations.
478bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// * non-linearity may happen around zero or with very high function values due to subnorms not
479bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		//   behaving well.
480bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const tcu::Vec4	functionValueForward	= (derivateFunc == DERIVATE_DFDX)
4819790daae5762b391f1a26bee4fb88a008fe4b583Jarkko Pöyry													? (function.evaluateAt((float)x + 2.0f, (float)y + 0.5f))
4829790daae5762b391f1a26bee4fb88a008fe4b583Jarkko Pöyry													: (function.evaluateAt((float)x + 0.5f, (float)y + 2.0f));
483bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const tcu::Vec4	functionValueBackward	= (derivateFunc == DERIVATE_DFDX)
4849790daae5762b391f1a26bee4fb88a008fe4b583Jarkko Pöyry													? (function.evaluateAt((float)x - 1.0f, (float)y + 0.5f))
4859790daae5762b391f1a26bee4fb88a008fe4b583Jarkko Pöyry													: (function.evaluateAt((float)x + 0.5f, (float)y - 1.0f));
486bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
487bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		bool	anyComponentFailed				= false;
488bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
489bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// check components separately
490bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		for (int c = 0; c < numComponents; ++c)
491bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		{
49259b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry			// Simulate interpolation. Add allowed interpolation error and round to target precision. Allow one half ULP (i.e. correct rounding)
49359b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry			const tcu::Interval	forwardComponent		(convertFloatFlushToZeroRtn(addErrorUlp((float)functionValueForward[c],  -0.5f, numVaryingSampleBits), minExponent, numBits),
49459b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry														 convertFloatFlushToZeroRtp(addErrorUlp((float)functionValueForward[c],  +0.5f, numVaryingSampleBits), minExponent, numBits));
49559b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry			const tcu::Interval	backwardComponent		(convertFloatFlushToZeroRtn(addErrorUlp((float)functionValueBackward[c], -0.5f, numVaryingSampleBits), minExponent, numBits),
49659b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry														 convertFloatFlushToZeroRtp(addErrorUlp((float)functionValueBackward[c], +0.5f, numVaryingSampleBits), minExponent, numBits));
497bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			const int			maxValueExp				= de::max(de::max(tcu::Float32(forwardComponent.lo()).exponent(),   tcu::Float32(forwardComponent.hi()).exponent()),
498bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry																  de::max(tcu::Float32(backwardComponent.lo()).exponent(),  tcu::Float32(backwardComponent.hi()).exponent()));
499bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
500d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			// subtraction in numerator will likely cause a cancellation of the most
501bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			// significant bits. Apply error bounds.
502bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
503d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const tcu::Interval	numerator				(forwardComponent - backwardComponent);
504d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const int			numeratorLoExp			= tcu::Float32(numerator.lo()).exponent();
505d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const int			numeratorHiExp			= tcu::Float32(numerator.hi()).exponent();
506d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const int			numeratorLoBitsLost		= de::max(0, maxValueExp - numeratorLoExp); //!< must clamp to zero since if forward and backward components have different
507d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const int			numeratorHiBitsLost		= de::max(0, maxValueExp - numeratorHiExp); //!< sign, numerator might have larger exponent than its operands.
508d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const int			numeratorLoBits			= de::max(0, numBits - numeratorLoBitsLost);
509d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const int			numeratorHiBits			= de::max(0, numBits - numeratorHiBitsLost);
510bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
51159b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry			const tcu::Interval	numeratorRange			(convertFloatFlushToZeroRtn((float)numerator.lo(), minExponent, numeratorLoBits),
51259b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry														 convertFloatFlushToZeroRtp((float)numerator.hi(), minExponent, numeratorHiBits));
513bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
514d9551dc8ecff19b0bfe50e0a463c49e99997b4a2Jarkko Pöyry			const tcu::Interval	divisionRange			= numeratorRange / 3.0f; // legal sample area is anywhere within this and neighboring pixels (i.e. size = 3)
51559b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry			const tcu::Interval	divisionResultRange		(convertFloatFlushToZeroRtn(addErrorUlp((float)divisionRange.lo(), -divisionErrorUlps, numBits), minExponent, numBits),
51659b032bc7f837293068a2ee0469274c6dfede801Jarkko Pöyry														 convertFloatFlushToZeroRtp(addErrorUlp((float)divisionRange.hi(), +divisionErrorUlps, numBits), minExponent, numBits));
517bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			const tcu::Interval	finalResultRange		(divisionResultRange.lo() - surfaceThreshold[c], divisionResultRange.hi() + surfaceThreshold[c]);
518bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
519bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			if (resultDerivative[c] >= finalResultRange.lo() && resultDerivative[c] <= finalResultRange.hi())
520bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			{
521bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				// value ok
522bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			}
523bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			else
524bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			{
525bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				if (numFailedPixels < MAX_FAILED_MESSAGES)
526bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry					log << tcu::TestLog::Message
527bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< "Error in pixel at " << x << ", " << y << " with component " << c << " (channel " << ("rgba"[c]) << ")\n"
528bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< "\tGot pixel value " << result.getPixelInt(x, y) << "\n"
529bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< "\t\tdFd" << ((derivateFunc == DERIVATE_DFDX) ? ('x') : ('y')) << " ~= " << resultDerivative[c] << "\n"
530bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< "\t\tdifference to a valid range: "
531bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry							<< ((resultDerivative[c] < finalResultRange.lo()) ? ("-") : ("+"))
532bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry							<< ((resultDerivative[c] < finalResultRange.lo()) ? (finalResultRange.lo() - resultDerivative[c]) : (resultDerivative[c] - finalResultRange.hi()))
533bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry							<< "\n"
534bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< "\tDerivative value range:\n"
535bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< "\t\tMin: " << finalResultRange.lo() << "\n"
536bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< "\t\tMax: " << finalResultRange.hi() << "\n"
537bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry						<< tcu::TestLog::EndMessage;
538bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
539bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				++numFailedPixels;
540bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				anyComponentFailed = true;
541bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			}
542bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		}
543bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
544bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		if (anyComponentFailed)
545bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			errorMask.setPixel(red, x, y);
546bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
547bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels >= MAX_FAILED_MESSAGES)
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "..." << TestLog::EndMessage;
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage;
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TriangleDerivateCase
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TriangleDerivateCase : public TestCase
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						TriangleDerivateCase	(Context& context, const char* name, const char* description);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~TriangleDerivateCase	(void);
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IterateResult		iterate					(void);
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void		setupRenderState		(deUint32 program) { DE_UNREF(program); }
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual bool		verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) = DE_NULL;
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2			getViewportSize			(void) const;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4			getSurfaceThreshold		(void) const;
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::DataType		m_dataType;
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision		m_precision;
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::DataType		m_coordDataType;
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision		m_coordPrecision;
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			m_fragmentSrc;
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4			m_coordMin;
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4			m_coordMax;
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4			m_derivScale;
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4			m_derivBias;
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	SurfaceType			m_surfaceType;
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					m_numSamples;
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32			m_hint;
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTriangleDerivateCase::TriangleDerivateCase (Context& context, const char* name, const char* description)
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCase			(context, name, description)
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_dataType		(glu::TYPE_LAST)
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_precision		(glu::PRECISION_LAST)
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_coordDataType	(glu::TYPE_LAST)
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_coordPrecision	(glu::PRECISION_LAST)
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_surfaceType		(SURFACETYPE_DEFAULT_FRAMEBUFFER)
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_numSamples		(0)
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_hint			(GL_DONT_CARE)
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_surfaceType != SURFACETYPE_DEFAULT_FRAMEBUFFER || m_numSamples == 0);
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6053c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTriangleDerivateCase::~TriangleDerivateCase (void)
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TriangleDerivateCase::deinit();
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic std::string genVertexSource (glu::DataType coordType, glu::Precision precision)
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(glu::isDataTypeFloatOrVec(coordType));
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* vertexTmpl =
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"#version 300 es\n"
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"in highp vec4 a_position;\n"
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"in ${PRECISION} ${DATATYPE} a_coord;\n"
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"out ${PRECISION} ${DATATYPE} v_coord;\n"
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main (void)\n"
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	gl_Position = a_position;\n"
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	v_coord = a_coord;\n"
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string> vertexParams;
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexParams["PRECISION"]	= glu::getPrecisionName(precision);
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	vertexParams["DATATYPE"]	= glu::getDataTypeName(coordType);
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::StringTemplate(vertexTmpl).specialize(vertexParams);
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::IVec2 TriangleDerivateCase::getViewportSize (void) const
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_surfaceType == SURFACETYPE_DEFAULT_FRAMEBUFFER)
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	width	= de::min<int>(m_context.getRenderTarget().getWidth(),	VIEWPORT_WIDTH);
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	height	= de::min<int>(m_context.getRenderTarget().getHeight(),	VIEWPORT_HEIGHT);
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::IVec2(width, height);
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::IVec2(FBO_WIDTH, FBO_HEIGHT);
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6453c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTriangleDerivateCase::IterateResult TriangleDerivateCase::iterate (void)
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&		gl				= m_context.getRenderContext().getFunctions();
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ShaderProgram	program			(m_context.getRenderContext(), glu::makeVtxFragSources(genVertexSource(m_coordDataType, m_coordPrecision), m_fragmentSrc));
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random					rnd				(deStringHash(getName()) ^ 0xbbc24);
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool					useFbo			= m_surfaceType != SURFACETYPE_DEFAULT_FRAMEBUFFER;
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32				fboFormat		= m_surfaceType == SURFACETYPE_FLOAT_FBO ? GL_RGBA32UI : GL_RGBA8;
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2			viewportSize	= getViewportSize();
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					viewportX		= useFbo ? 0 : rnd.getInt(0, m_context.getRenderTarget().getWidth()		- viewportSize.x());
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int					viewportY		= useFbo ? 0 : rnd.getInt(0, m_context.getRenderTarget().getHeight()	- viewportSize.y());
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AutoFbo						fbo				(gl);
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	AutoRbo						rbo				(gl);
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TextureLevel			result;
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << program;
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!program.isOk())
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Compile failed");
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useFbo)
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::Message
667b2e583dfcd8aa0d4ef254f841213fcf724b2b193Jarkko Pöyry						   << "Rendering to FBO, format = " << glu::getTextureFormatStr(fboFormat)
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   << ", samples = " << m_numSamples
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   << TestLog::EndMessage;
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fbo.gen();
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		rbo.gen();
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindRenderbuffer(GL_RENDERBUFFER, *rbo);
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, fboFormat, viewportSize.x(), viewportSize.y());
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo);
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *rbo);
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
681bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	{
682bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
683bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
684bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		m_testCtx.getLog()
685bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< TestLog::Message
686bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "Rendering to default framebuffer\n"
687bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "\tColor depth: R=" << pixelFormat.redBits << ", G=" << pixelFormat.greenBits << ", B=" << pixelFormat.blueBits << ", A=" << pixelFormat.alphaBits
688bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< TestLog::EndMessage;
689bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry	}
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testCtx.getLog() << TestLog::Message << "in: " << m_coordMin << " -> " << m_coordMax << "\n"
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << "v_coord.x = in.x * x\n"
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << "v_coord.y = in.y * y\n"
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << "v_coord.z = in.z * (x+y)/2\n"
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										   << "v_coord.w = in.w * (1 - (x+y)/2)\n"
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   << TestLog::EndMessage
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   << TestLog::Message << "u_scale: " << m_derivScale << ", u_bias: " << m_derivBias << " (displayed values have scale/bias removed)" << TestLog::EndMessage
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   << TestLog::Message << "Viewport: " << viewportSize.x() << "x" << viewportSize.y() << TestLog::EndMessage
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   << TestLog::Message << "GL_FRAGMENT_SHADER_DERIVATE_HINT: " << glu::getHintModeStr(m_hint) << TestLog::EndMessage;
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Draw
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float positions[] =
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			-1.0f, -1.0f, 0.0f, 1.0f,
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			-1.0f,  1.0f, 0.0f, 1.0f,
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 1.0f, -1.0f, 0.0f, 1.0f,
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 1.0f,  1.0f, 0.0f, 1.0f
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float coords[] =
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMin.x(), m_coordMin.y(), m_coordMin.z(),							m_coordMax.w(),
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMin.x(), m_coordMax.y(), (m_coordMin.z()+m_coordMax.z())*0.5f,	(m_coordMin.w()+m_coordMax.w())*0.5f,
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMax.x(), m_coordMin.y(), (m_coordMin.z()+m_coordMax.z())*0.5f,	(m_coordMin.w()+m_coordMax.w())*0.5f,
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMax.x(), m_coordMax.y(), m_coordMax.z(),							m_coordMin.w()
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding vertexArrays[] =
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("a_position",	4, 4, 0, &positions[0]),
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("a_coord",		4, 4, 0, &coords[0])
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint16 indices[] = { 0, 2, 1, 2, 3, 1 };
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
726bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		gl.disable(GL_DITHER);
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.useProgram(program.getProgram());
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	scaleLoc	= gl.getUniformLocation(program.getProgram(), "u_scale");
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	biasLoc		= gl.getUniformLocation(program.getProgram(), "u_bias");
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			switch (m_dataType)
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case glu::TYPE_FLOAT:
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform1f(scaleLoc, m_derivScale.x());
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform1f(biasLoc, m_derivBias.x());
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case glu::TYPE_FLOAT_VEC2:
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform2fv(scaleLoc, 1, m_derivScale.getPtr());
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform2fv(biasLoc, 1, m_derivBias.getPtr());
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case glu::TYPE_FLOAT_VEC3:
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform3fv(scaleLoc, 1, m_derivScale.getPtr());
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform3fv(biasLoc, 1, m_derivBias.getPtr());
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				case glu::TYPE_FLOAT_VEC4:
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform4fv(scaleLoc, 1, m_derivScale.getPtr());
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					gl.uniform4fv(biasLoc, 1, m_derivBias.getPtr());
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				default:
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(false);
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gls::setupDefaultUniforms(m_context.getRenderContext(), program.getProgram());
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setupRenderState(program.getProgram());
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.hint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT, m_hint);
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Setup program state");
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.viewport(viewportX, viewportY, viewportSize.x(), viewportSize.y());
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Read back results
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		isMSAA		= useFbo && m_numSamples > 0;
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		AutoFbo			resFbo		(gl);
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		AutoRbo			resRbo		(gl);
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Resolve if necessary
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isMSAA)
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			resFbo.gen();
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			resRbo.gen();
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindRenderbuffer(GL_RENDERBUFFER, *resRbo);
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, fboFormat, viewportSize.x(), viewportSize.y());
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *resFbo);
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *resRbo);
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.blitFramebuffer(0, 0, viewportSize.x(), viewportSize.y(), 0, 0, viewportSize.x(), viewportSize.y(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			GLU_EXPECT_NO_ERROR(gl.getError(), "Resolve blit");
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *resFbo);
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_surfaceType)
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SURFACETYPE_DEFAULT_FRAMEBUFFER:
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SURFACETYPE_UNORM_FBO:
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.setStorage(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), viewportSize.x(), viewportSize.y());
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, result);
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SURFACETYPE_FLOAT_FBO:
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::TextureFormat	dataFormat		(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::TextureFormat	transferFormat	(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result.setStorage(dataFormat, viewportSize.x(), viewportSize.y());
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				glu::readPixels(m_context.getRenderContext(), viewportX, viewportY,
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								tcu::PixelBufferAccess(transferFormat, result.getWidth(), result.getHeight(), result.getDepth(), result.getAccess().getDataPtr()));
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Verify
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Surface errorMask(result.getWidth(), result.getHeight());
826c215aaa83047ebbaabafef7acd71275a256da6abDejan Mircevski		tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool isOk = verify(result.getAccess(), errorMask.getAccess());
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::ImageSet("Result", "Result images")
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						   << TestLog::Image("Rendered", "Rendered image", result);
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testCtx.getLog() << TestLog::Image("ErrorMask", "Error mask", errorMask);
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.getLog() << TestLog::EndImageSet;
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								isOk ? "Pass"				: "Image comparison failed");
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return STOP;
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytcu::Vec4 TriangleDerivateCase::getSurfaceThreshold (void) const
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_surfaceType)
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SURFACETYPE_DEFAULT_FRAMEBUFFER:
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::PixelFormat	pixelFormat		= m_context.getRenderTarget().getPixelFormat();
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::IVec4		channelBits		(pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits);
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::IVec4		intThreshold	= tcu::IVec4(1) << (8 - channelBits);
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4			normThreshold	= intThreshold.asFloat() / 255.0f;
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return normThreshold;
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SURFACETYPE_UNORM_FBO:				return tcu::IVec4(1).asFloat() / 255.0f;
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case SURFACETYPE_FLOAT_FBO:				return tcu::Vec4(0.0f);
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return tcu::Vec4(0.0f);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ConstantDerivateCase
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass ConstantDerivateCase : public TriangleDerivateCase
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						ConstantDerivateCase		(Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type);
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~ConstantDerivateCase		(void) {}
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init						(void);
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				verify						(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DerivateFunc		m_func;
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8843c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConstantDerivateCase::ConstantDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type)
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TriangleDerivateCase	(context, name, description)
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_func				(func)
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_dataType			= type;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_precision			= glu::PRECISION_HIGHP;
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordDataType		= m_dataType;
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordPrecision	= m_precision;
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ConstantDerivateCase::init (void)
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char* fragmentTmpl =
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"#version 300 es\n"
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"layout(location = 0) out mediump vec4 o_color;\n"
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main (void)\n"
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	${PRECISION} ${DATATYPE} res = ${FUNC}(${VALUE}) * u_scale + u_bias;\n"
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	o_color = ${CAST_TO_OUTPUT};\n"
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string> fragmentParams;
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["PRECISION"]			= glu::getPrecisionName(m_precision);
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["DATATYPE"]			= glu::getDataTypeName(m_dataType);
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["FUNC"]				= getDerivateFuncName(m_func);
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["VALUE"]				= m_dataType == glu::TYPE_FLOAT_VEC4 ? "vec4(1.0, 7.2, -1e5, 0.0)" :
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec3(1e2, 8.0, 0.01)" :
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec2(-0.0, 2.7)" :
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  /* TYPE_FLOAT */					   "7.7";
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["CAST_TO_OUTPUT"]	= m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" :
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" :
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" :
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										  /* TYPE_FLOAT */					   "vec4(res, 0.0, 0.0, 1.0)";
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fragmentSrc = tcu::StringTemplate(fragmentTmpl).specialize(fragmentParams);
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_derivScale	= tcu::Vec4(1e3f, 1e3f, 1e3f, 1e3f);
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_derivBias		= tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ConstantDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4 reference	(0.0f); // Derivate of constant argument should always be 0
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4	threshold	= getSurfaceThreshold() / abs(m_derivScale);
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								  reference, threshold, m_derivScale, m_derivBias);
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// LinearDerivateCase
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass LinearDerivateCase : public TriangleDerivateCase
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						LinearDerivateCase		(Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples, const char* fragmentSrcTmpl);
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~LinearDerivateCase		(void) {}
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init					(void);
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DerivateFunc		m_func;
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string			m_fragmentTmpl;
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryLinearDerivateCase::LinearDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples, const char* fragmentSrcTmpl)
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TriangleDerivateCase	(context, name, description)
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_func				(func)
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_fragmentTmpl		(fragmentSrcTmpl)
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_dataType			= type;
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_precision			= precision;
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordDataType		= m_dataType;
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordPrecision	= m_precision;
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_hint				= hint;
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_surfaceType		= surfaceType;
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_numSamples		= numSamples;
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid LinearDerivateCase::init (void)
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	viewportSize	= getViewportSize();
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			w				= float(viewportSize.x());
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			h				= float(viewportSize.y());
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool			packToInt		= m_surfaceType == SURFACETYPE_FLOAT_FBO;
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string>	fragmentParams;
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["OUTPUT_TYPE"]		= glu::getDataTypeName(packToInt ? glu::TYPE_UINT_VEC4 : glu::TYPE_FLOAT_VEC4);
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["OUTPUT_PREC"]		= glu::getPrecisionName(packToInt ? glu::PRECISION_HIGHP : m_precision);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["PRECISION"]			= glu::getPrecisionName(m_precision);
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["DATATYPE"]			= glu::getDataTypeName(m_dataType);
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	fragmentParams["FUNC"]				= getDerivateFuncName(m_func);
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (packToInt)
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["CAST_TO_OUTPUT"]	= m_dataType == glu::TYPE_FLOAT_VEC4 ? "floatBitsToUint(res)" :
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  m_dataType == glu::TYPE_FLOAT_VEC3 ? "floatBitsToUint(vec4(res, 1.0))" :
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  m_dataType == glu::TYPE_FLOAT_VEC2 ? "floatBitsToUint(vec4(res, 0.0, 1.0))" :
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  /* TYPE_FLOAT */					   "floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))";
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["CAST_TO_OUTPUT"]	= m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" :
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" :
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" :
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  /* TYPE_FLOAT */					   "vec4(res, 0.0, 0.0, 1.0)";
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_fragmentSrc = tcu::StringTemplate(m_fragmentTmpl.c_str()).specialize(fragmentParams);
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_precision)
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::PRECISION_HIGHP:
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMin = tcu::Vec4(-97.f, 0.2f, 71.f, 74.f);
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMax = tcu::Vec4(-13.2f, -77.f, 44.f, 76.f);
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::PRECISION_MEDIUMP:
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMin = tcu::Vec4(-37.0f, 47.f, -7.f, 0.0f);
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMax = tcu::Vec4(-1.0f, 12.f, 7.f, 19.f);
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::PRECISION_LOWP:
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMin = tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f);
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_coordMax = tcu::Vec4(1.0f, 1.0f, -1.0f, -1.0f);
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_surfaceType == SURFACETYPE_FLOAT_FBO)
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// No scale or bias used for accuracy.
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_derivScale	= tcu::Vec4(1.0f);
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_derivBias		= tcu::Vec4(0.0f);
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute scale - bias that normalizes to 0..1 range.
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4 dx = (m_coordMax - m_coordMin) / tcu::Vec4(w, w, w*0.5f, -w*0.5f);
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4 dy = (m_coordMax - m_coordMin) / tcu::Vec4(h, h, h*0.5f, -h*0.5f);
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_func)
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case DERIVATE_DFDX:
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_derivScale = 0.5f / dx;
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case DERIVATE_DFDY:
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_derivScale = 0.5f / dy;
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case DERIVATE_FWIDTH:
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_derivScale = 0.5f / (tcu::abs(dx) + tcu::abs(dy));
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_derivBias = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		xScale				= tcu::Vec4(1.0f, 0.0f, 0.5f, -0.5f);
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		yScale				= tcu::Vec4(0.0f, 1.0f, 0.5f, -0.5f);
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		surfaceThreshold	= getSurfaceThreshold() / abs(m_derivScale);
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY)
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			isX			= m_func == DERIVATE_DFDX;
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			div			= isX ? float(result.getWidth()) : float(result.getHeight());
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		scale		= isX ? xScale : yScale;
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		reference	= ((m_coordMax - m_coordMin) / div) * scale;
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		opThreshold	= getDerivateThreshold(m_precision, m_coordMin*scale, m_coordMax*scale, reference);
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		threshold	= max(surfaceThreshold, opThreshold);
1066bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const int			numComps	= glu::getDataTypeFloatScalars(m_dataType);
1067bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1068bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		m_testCtx.getLog()
1069bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::Message
1070bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "Verifying result image.\n"
1071bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "\tValid derivative is " << LogVecComps(reference, numComps) << " with threshold " << LogVecComps(threshold, numComps)
1072bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::EndMessage;
1073bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1074bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// short circuit if result is strictly within the normal value error bounds.
1075bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// This improves performance significantly.
1076bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
1077bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry								   reference, threshold, m_derivScale, m_derivBias,
1078bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry								   LOG_NOTHING))
1079bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		{
1080bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			m_testCtx.getLog()
1081bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				<< tcu::TestLog::Message
1082bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				<< "No incorrect derivatives found, result valid."
1083bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				<< tcu::TestLog::EndMessage;
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1085bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			return true;
1086bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		}
1087bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1088bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// some pixels exceed error bounds calculated for normal values. Verify that these
1089bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// potentially invalid pixels are in fact valid due to (for example) subnorm flushing.
1090bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1091bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		m_testCtx.getLog()
1092bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::Message
1093bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n"
1094bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "\tVerifying each result derivative is within its range of legal result values."
1095bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::EndMessage;
1096bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1097bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		{
1098bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			const tcu::IVec2			viewportSize	= getViewportSize();
1099bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			const float					w				= float(viewportSize.x());
1100bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			const float					h				= float(viewportSize.y());
1101bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			const tcu::Vec4				valueRamp		= (m_coordMax - m_coordMin);
1102bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			Linear2DFunctionEvaluator	function;
1103bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1104bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(0, tcu::Vec3(valueRamp.x() / w, 0.0f, m_coordMin.x()));
1105bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(1, tcu::Vec3(0.0f, valueRamp.y() / h, m_coordMin.y()));
1106bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(2, tcu::Vec3(valueRamp.z() / w, valueRamp.z() / h, m_coordMin.z() + m_coordMin.z()) / 2.0f);
1107bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(3, tcu::Vec3(-valueRamp.w() / w, -valueRamp.w() / h, m_coordMax.w() + m_coordMax.w()) / 2.0f);
1108bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1109bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			return reverifyConstantDerivateWithFlushRelaxations(m_testCtx.getLog(), result, errorMask,
1110bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry																m_dataType, m_precision, m_derivScale,
1111bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry																m_derivBias, surfaceThreshold, m_func,
1112bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry																function);
1113bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		}
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_func == DERIVATE_FWIDTH);
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			w			= float(result.getWidth());
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			h			= float(result.getHeight());
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		dx			= ((m_coordMax - m_coordMin) / w) * xScale;
11223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		dy			= ((m_coordMax - m_coordMin) / h) * yScale;
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		reference	= tcu::abs(dx) + tcu::abs(dy);
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		dxThreshold	= getDerivateThreshold(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx);
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		dyThreshold	= getDerivateThreshold(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy);
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		threshold	= max(surfaceThreshold, max(dxThreshold, dyThreshold));
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType,
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  reference, threshold, m_derivScale, m_derivBias);
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// TextureDerivateCase
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TextureDerivateCase : public TriangleDerivateCase
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						TextureDerivateCase		(Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples);
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						~TextureDerivateCase	(void);
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				init					(void);
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				deinit					(void);
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void				setupRenderState		(deUint32 program);
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool				verify					(const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask);
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DerivateFunc		m_func;
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4			m_texValueMin;
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4			m_texValueMax;
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Texture2D*		m_texture;
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11563c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureDerivateCase::TextureDerivateCase (Context& context, const char* name, const char* description, DerivateFunc func, glu::DataType type, glu::Precision precision, deUint32 hint, SurfaceType surfaceType, int numSamples)
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TriangleDerivateCase	(context, name, description)
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_func				(func)
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_texture				(DE_NULL)
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_dataType			= type;
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_precision			= precision;
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordDataType		= glu::TYPE_FLOAT_VEC2;
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordPrecision	= glu::PRECISION_HIGHP;
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_hint				= hint;
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_surfaceType		= surfaceType;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_numSamples		= numSamples;
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11703c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureDerivateCase::~TextureDerivateCase (void)
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_texture;
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureDerivateCase::init (void)
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Generate shader
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char* fragmentTmpl =
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in highp vec2 v_coord;\n"
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} sampler2D u_sampler;\n"
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} vec4 tex = texture(u_sampler, v_coord);\n"
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res = ${FUNC}(tex${SWIZZLE}) * u_scale + u_bias;\n"
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n";
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			packToInt		= m_surfaceType == SURFACETYPE_FLOAT_FBO;
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		map<string, string> fragmentParams;
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["OUTPUT_TYPE"]		= glu::getDataTypeName(packToInt ? glu::TYPE_UINT_VEC4 : glu::TYPE_FLOAT_VEC4);
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["OUTPUT_PREC"]		= glu::getPrecisionName(packToInt ? glu::PRECISION_HIGHP : m_precision);
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["PRECISION"]			= glu::getPrecisionName(m_precision);
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["DATATYPE"]			= glu::getDataTypeName(m_dataType);
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["FUNC"]				= getDerivateFuncName(m_func);
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		fragmentParams["SWIZZLE"]			= m_dataType == glu::TYPE_FLOAT_VEC4 ? "" :
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  m_dataType == glu::TYPE_FLOAT_VEC3 ? ".xyz" :
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  m_dataType == glu::TYPE_FLOAT_VEC2 ? ".xy" :
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											  /* TYPE_FLOAT */					   ".x";
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (packToInt)
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fragmentParams["CAST_TO_OUTPUT"]	= m_dataType == glu::TYPE_FLOAT_VEC4 ? "floatBitsToUint(res)" :
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  m_dataType == glu::TYPE_FLOAT_VEC3 ? "floatBitsToUint(vec4(res, 1.0))" :
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  m_dataType == glu::TYPE_FLOAT_VEC2 ? "floatBitsToUint(vec4(res, 0.0, 1.0))" :
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  /* TYPE_FLOAT */					   "floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))";
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			fragmentParams["CAST_TO_OUTPUT"]	= m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" :
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" :
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" :
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												  /* TYPE_FLOAT */					   "vec4(res, 0.0, 0.0, 1.0)";
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_fragmentSrc = tcu::StringTemplate(fragmentTmpl).specialize(fragmentParams);
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Texture size matches viewport and nearest sampling is used. Thus texture sampling
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// is equal to just interpolating the texture value range.
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Determine value range for texture.
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (m_precision)
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::PRECISION_HIGHP:
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texValueMin = tcu::Vec4(-97.f, 0.2f, 71.f, 74.f);
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texValueMax = tcu::Vec4(-13.2f, -77.f, 44.f, 76.f);
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::PRECISION_MEDIUMP:
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texValueMin = tcu::Vec4(-37.0f, 47.f, -7.f, 0.0f);
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texValueMax = tcu::Vec4(-1.0f, 12.f, 7.f, 19.f);
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case glu::PRECISION_LOWP:
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texValueMin = tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f);
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_texValueMax = tcu::Vec4(1.0f, 1.0f, -1.0f, -1.0f);
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Lowp and mediump cases use RGBA16F format, while highp uses RGBA32F.
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::IVec2 viewportSize = getViewportSize();
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!m_texture);
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_texture = new glu::Texture2D(m_context.getRenderContext(), m_precision == glu::PRECISION_HIGHP ? GL_RGBA32F : GL_RGBA16F, viewportSize.x(), viewportSize.y());
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_texture->getRefTexture().allocLevel(0);
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Texture coordinates
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordMin = tcu::Vec4(0.0f);
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_coordMax = tcu::Vec4(1.0f);
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Fill with gradients.
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::PixelBufferAccess level0 = m_texture->getRefTexture().getLevel(0);
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int y = 0; y < level0.getHeight(); y++)
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int x = 0; x < level0.getWidth(); x++)
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		xf		= (float(x)+0.5f) / float(level0.getWidth());
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		yf		= (float(y)+0.5f) / float(level0.getHeight());
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec4	s		= tcu::Vec4(xf, yf, (xf+yf)/2.0f, 1.0f - (xf+yf)/2.0f);
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				level0.setPixel(m_texValueMin + (m_texValueMax - m_texValueMin)*s, x, y);
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_texture->upload();
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_surfaceType == SURFACETYPE_FLOAT_FBO)
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// No scale or bias used for accuracy.
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_derivScale	= tcu::Vec4(1.0f);
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_derivBias		= tcu::Vec4(0.0f);
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Compute scale - bias that normalizes to 0..1 range.
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::IVec2	viewportSize	= getViewportSize();
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			w				= float(viewportSize.x());
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			h				= float(viewportSize.y());
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		dx				= (m_texValueMax - m_texValueMin) / tcu::Vec4(w, w, w*0.5f, -w*0.5f);
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		dy				= (m_texValueMax - m_texValueMin) / tcu::Vec4(h, h, h*0.5f, -h*0.5f);
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_func)
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case DERIVATE_DFDX:
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_derivScale = 0.5f / dx;
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case DERIVATE_DFDY:
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_derivScale = 0.5f / dy;
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case DERIVATE_FWIDTH:
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_derivScale = 0.5f / (tcu::abs(dx) + tcu::abs(dy));
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_derivBias = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureDerivateCase::deinit (void)
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	delete m_texture;
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_texture = DE_NULL;
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureDerivateCase::setupRenderState (deUint32 program)
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl			= m_context.getRenderContext().getFunctions();
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int				texUnit		= 1;
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.activeTexture	(GL_TEXTURE0+texUnit);
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindTexture		(GL_TEXTURE_2D, m_texture->getGLTexture());
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.texParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.texParameteri	(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.texParameteri	(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.texParameteri	(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform1i		(gl.getUniformLocation(program, "u_sampler"), texUnit);
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask)
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Edges are ignored in comparison
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (result.getWidth() < 2 || result.getHeight() < 2)
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::NotSupportedError("Too small viewport");
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::ConstPixelBufferAccess	compareArea			= tcu::getSubregion(result, 1, 1, result.getWidth()-2, result.getHeight()-2);
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::PixelBufferAccess		maskArea			= tcu::getSubregion(errorMask, 1, 1, errorMask.getWidth()-2, errorMask.getHeight()-2);
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				xScale				= tcu::Vec4(1.0f, 0.0f, 0.5f, -0.5f);
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				yScale				= tcu::Vec4(0.0f, 1.0f, 0.5f, -0.5f);
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float					w					= float(result.getWidth());
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float					h					= float(result.getHeight());
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				surfaceThreshold	= getSurfaceThreshold() / abs(m_derivScale);
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY)
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			isX			= m_func == DERIVATE_DFDX;
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			div			= isX ? w : h;
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		scale		= isX ? xScale : yScale;
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		reference	= ((m_texValueMax - m_texValueMin) / div) * scale;
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		opThreshold	= getDerivateThreshold(m_precision, m_texValueMin*scale, m_texValueMax*scale, reference);
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		threshold	= max(surfaceThreshold, opThreshold);
1361bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		const int			numComps	= glu::getDataTypeFloatScalars(m_dataType);
1362bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1363bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		m_testCtx.getLog()
1364bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::Message
1365bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "Verifying result image.\n"
1366bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "\tValid derivative is " << LogVecComps(reference, numComps) << " with threshold " << LogVecComps(threshold, numComps)
1367bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::EndMessage;
1368bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1369bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// short circuit if result is strictly within the normal value error bounds.
1370bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// This improves performance significantly.
1371bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
1372bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry								   reference, threshold, m_derivScale, m_derivBias,
1373bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry								   LOG_NOTHING))
1374bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		{
1375bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			m_testCtx.getLog()
1376bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				<< tcu::TestLog::Message
1377bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				<< "No incorrect derivatives found, result valid."
1378bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry				<< tcu::TestLog::EndMessage;
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1380bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			return true;
1381bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		}
1382bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1383bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// some pixels exceed error bounds calculated for normal values. Verify that these
1384bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		// potentially invalid pixels are in fact valid due to (for example) subnorm flushing.
1385bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1386bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		m_testCtx.getLog()
1387bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::Message
1388bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "Initial verification failed, verifying image by calculating accurate error bounds for each result pixel.\n"
1389bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< "\tVerifying each result derivative is within its range of legal result values."
1390bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			<< tcu::TestLog::EndMessage;
1391bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1392bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		{
1393bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			const tcu::Vec4				valueRamp		= (m_texValueMax - m_texValueMin);
1394bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			Linear2DFunctionEvaluator	function;
1395bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1396bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(0, tcu::Vec3(valueRamp.x() / w, 0.0f, m_texValueMin.x()));
1397bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(1, tcu::Vec3(0.0f, valueRamp.y() / h, m_texValueMin.y()));
1398bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(2, tcu::Vec3(valueRamp.z() / w, valueRamp.z() / h, m_texValueMin.z() + m_texValueMin.z()) / 2.0f);
1399bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			function.matrix.setRow(3, tcu::Vec3(-valueRamp.w() / w, -valueRamp.w() / h, m_texValueMax.w() + m_texValueMax.w()) / 2.0f);
1400bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry
1401bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry			return reverifyConstantDerivateWithFlushRelaxations(m_testCtx.getLog(), compareArea, maskArea,
1402bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry																m_dataType, m_precision, m_derivScale,
1403bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry																m_derivBias, surfaceThreshold, m_func,
1404bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry																function);
1405bd4d098088a5b205c7e7d8dc0bec140d2fa55446Jarkko Pöyry		}
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_func == DERIVATE_FWIDTH);
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	dx			= ((m_texValueMax - m_texValueMin) / w) * xScale;
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	dy			= ((m_texValueMax - m_texValueMin) / h) * yScale;
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	reference	= tcu::abs(dx) + tcu::abs(dy);
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	dxThreshold	= getDerivateThreshold(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx);
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	dyThreshold	= getDerivateThreshold(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy);
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	threshold	= max(surfaceThreshold, max(dxThreshold, dyThreshold));
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									  reference, threshold, m_derivScale, m_derivBias);
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14223c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderDerivateTests::ShaderDerivateTests (Context& context)
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TestCaseGroup(context, "derivate", "Derivate Function Tests")
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14273c827367444ee418f129b2c238299f49d3264554Jarkko PoyryShaderDerivateTests::~ShaderDerivateTests (void)
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct FunctionSpec
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		name;
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DerivateFunc	function;
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::DataType	dataType;
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::Precision	precision;
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	FunctionSpec (const std::string& name_, DerivateFunc function_, glu::DataType dataType_, glu::Precision precision_)
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: name		(name_)
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, function	(function_)
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, dataType	(dataType_)
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, precision	(precision_)
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ShaderDerivateTests::init (void)
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		description;
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		source;
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_linearDerivateCases[] =
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"linear",
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Basic derivate of linearly interpolated argument",
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res = ${FUNC}(v_coord) * u_scale + u_bias;\n"
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in_function",
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Derivate of linear function argument",
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"${PRECISION} ${DATATYPE} computeRes (${PRECISION} ${DATATYPE} value)\n"
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	return ${FUNC}(v_coord) * u_scale + u_bias;\n"
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"\n"
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res = computeRes(v_coord);\n"
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"static_if",
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Derivate of linearly interpolated value in static if",
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res;\n"
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	if (false)\n"
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		res = ${FUNC}(-v_coord) * u_scale + u_bias;\n"
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	else\n"
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		res = ${FUNC}(v_coord) * u_scale + u_bias;\n"
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"static_loop",
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Derivate of linearly interpolated value in static loop",
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n"
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	for (int i = 0; i < 2; i++)\n"
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		res += ${FUNC}(v_coord * float(i));\n"
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	res = res * u_scale + u_bias;\n"
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"static_switch",
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Derivate of linearly interpolated value in static switch",
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res;\n"
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	switch (1)\n"
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	{\n"
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		case 0:	res = ${FUNC}(-v_coord) * u_scale + u_bias;	break;\n"
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		case 1:	res = ${FUNC}(v_coord) * u_scale + u_bias;	break;\n"
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	}\n"
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform_if",
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Derivate of linearly interpolated value in uniform if",
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform bool ub_true;\n"
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res;\n"
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	if (ub_true)"
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		res = ${FUNC}(v_coord) * u_scale + u_bias;\n"
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	else\n"
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		res = ${FUNC}(-v_coord) * u_scale + u_bias;\n"
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform_loop",
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Derivate of linearly interpolated value in uniform loop",
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform int ui_two;\n"
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n"
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	for (int i = 0; i < ui_two; i++)\n"
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		res += ${FUNC}(v_coord * float(i));\n"
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	res = res * u_scale + u_bias;\n"
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform_switch",
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"Derivate of linearly interpolated value in uniform switch",
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"#version 300 es\n"
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"in ${PRECISION} ${DATATYPE} v_coord;\n"
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_scale;\n"
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform ${PRECISION} ${DATATYPE} u_bias;\n"
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"uniform int ui_one;\n"
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"void main (void)\n"
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"{\n"
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	${PRECISION} ${DATATYPE} res;\n"
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	switch (ui_one)\n"
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	{\n"
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		case 0:	res = ${FUNC}(-v_coord) * u_scale + u_bias;	break;\n"
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"		case 1:	res = ${FUNC}(v_coord) * u_scale + u_bias;	break;\n"
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	}\n"
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"	o_color = ${CAST_TO_OUTPUT};\n"
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			"}\n"
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		},
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SurfaceType		surfaceType;
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				numSamples;
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_fboConfigs[] =
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "fbo",		SURFACETYPE_DEFAULT_FRAMEBUFFER,	0 },
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "fbo_msaa2",	SURFACETYPE_UNORM_FBO,				2 },
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "fbo_msaa4",	SURFACETYPE_UNORM_FBO,				4 },
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "fbo_float",	SURFACETYPE_FLOAT_FBO,				0 },
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		hint;
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_hints[] =
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "fastest",	GL_FASTEST	},
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "nicest",		GL_NICEST	},
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SurfaceType		surfaceType;
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				numSamples;
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_hintFboConfigs[] =
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "default",		SURFACETYPE_DEFAULT_FRAMEBUFFER,	0 },
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "fbo_msaa4",		SURFACETYPE_UNORM_FBO,				4 },
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "fbo_float",		SURFACETYPE_FLOAT_FBO,				0 }
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		SurfaceType		surfaceType;
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int				numSamples;
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint32		hint;
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_textureConfigs[] =
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "basic",			SURFACETYPE_DEFAULT_FRAMEBUFFER,	0,	GL_DONT_CARE	},
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "msaa4",			SURFACETYPE_UNORM_FBO,				4,	GL_DONT_CARE	},
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "float_fastest",	SURFACETYPE_FLOAT_FBO,				0,	GL_FASTEST		},
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ "float_nicest",	SURFACETYPE_FLOAT_FBO,				0,	GL_NICEST		},
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// .dfdx, .dfdy, .fwidth
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int funcNdx = 0; funcNdx < DERIVATE_LAST; funcNdx++)
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const DerivateFunc			function		= DerivateFunc(funcNdx);
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::TestCaseGroup* const	functionGroup	= new tcu::TestCaseGroup(m_testCtx, getDerivateFuncCaseName(function), getDerivateFuncName(function));
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addChild(functionGroup);
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .constant - no precision variants, checks that derivate of constant arguments is 0
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* const constantGroup = new tcu::TestCaseGroup(m_testCtx, "constant", "Derivate of constant argument");
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			functionGroup->addChild(constantGroup);
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vecSize = 1; vecSize <= 4; vecSize++)
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const glu::DataType dataType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				constantGroup->addChild(new ConstantDerivateCase(m_context, glu::getDataTypeName(dataType), "", function, dataType));
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Cases based on LinearDerivateCase
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_linearDerivateCases); caseNdx++)
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* const linearCaseGroup	= new tcu::TestCaseGroup(m_testCtx, s_linearDerivateCases[caseNdx].name, s_linearDerivateCases[caseNdx].description);
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*			source					= s_linearDerivateCases[caseNdx].source;
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			functionGroup->addChild(linearCaseGroup);
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vecSize = 1; vecSize <= 4; vecSize++)
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::DataType		dataType		= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::Precision	precision		= glu::Precision(precNdx);
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const SurfaceType		surfaceType		= SURFACETYPE_DEFAULT_FRAMEBUFFER;
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const int				numSamples		= 0;
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32			hint			= GL_DONT_CARE;
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ostringstream			caseName;
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (caseNdx != 0 && precision == glu::PRECISION_LOWP)
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						continue; // Skip as lowp doesn't actually produce any bits when rendered to default FB.
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					linearCaseGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples, source));
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Fbo cases
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_fboConfigs); caseNdx++)
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup*	const	fboGroup		= new tcu::TestCaseGroup(m_testCtx, s_fboConfigs[caseNdx].name, "Derivate usage when rendering into FBO");
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*					source			= s_linearDerivateCases[0].source; // use source from .linear group
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const SurfaceType			surfaceType		= s_fboConfigs[caseNdx].surfaceType;
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int					numSamples		= s_fboConfigs[caseNdx].numSamples;
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			functionGroup->addChild(fboGroup);
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int vecSize = 1; vecSize <= 4; vecSize++)
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::DataType		dataType		= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const glu::Precision	precision		= glu::Precision(precNdx);
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint32			hint			= GL_DONT_CARE;
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					ostringstream			caseName;
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP)
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					fboGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples, source));
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .fastest, .nicest
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int hintCaseNdx = 0; hintCaseNdx < DE_LENGTH_OF_ARRAY(s_hints); hintCaseNdx++)
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* const	hintGroup		= new tcu::TestCaseGroup(m_testCtx, s_hints[hintCaseNdx].name, "Shader derivate hints");
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*					source			= s_linearDerivateCases[0].source; // use source from .linear group
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32				hint			= s_hints[hintCaseNdx].hint;
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			functionGroup->addChild(hintGroup);
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int fboCaseNdx = 0; fboCaseNdx < DE_LENGTH_OF_ARRAY(s_hintFboConfigs); fboCaseNdx++)
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::TestCaseGroup*	const	fboGroup		= new tcu::TestCaseGroup(m_testCtx, s_hintFboConfigs[fboCaseNdx].name, "");
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const SurfaceType			surfaceType		= s_hintFboConfigs[fboCaseNdx].surfaceType;
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int					numSamples		= s_hintFboConfigs[fboCaseNdx].numSamples;
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				hintGroup->addChild(fboGroup);
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int vecSize = 1; vecSize <= 4; vecSize++)
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const glu::DataType		dataType		= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const glu::Precision	precision		= glu::Precision(precNdx);
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						ostringstream			caseName;
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP)
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						fboGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples, source));
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// .texture
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::TestCaseGroup* const textureGroup = new tcu::TestCaseGroup(m_testCtx, "texture", "Derivate of texture lookup result");
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			functionGroup->addChild(textureGroup);
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int texCaseNdx = 0; texCaseNdx < DE_LENGTH_OF_ARRAY(s_textureConfigs); texCaseNdx++)
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::TestCaseGroup*	const	caseGroup		= new tcu::TestCaseGroup(m_testCtx, s_textureConfigs[texCaseNdx].name, "");
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const SurfaceType			surfaceType		= s_textureConfigs[texCaseNdx].surfaceType;
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int					numSamples		= s_textureConfigs[texCaseNdx].numSamples;
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const deUint32				hint			= s_textureConfigs[texCaseNdx].hint;
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				textureGroup->addChild(caseGroup);
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int vecSize = 1; vecSize <= 4; vecSize++)
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const glu::DataType		dataType		= vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const glu::Precision	precision		= glu::Precision(precNdx);
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						ostringstream			caseName;
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP)
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						caseGroup->addChild(new TextureDerivateCase(m_context, caseName.str().c_str(), "", function, dataType, precision, hint, surfaceType, numSamples));
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // Functional
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gles3
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
1806