13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL (ES) 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 Texture test utilities.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsTextureTestUtil.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDefs.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuStringTemplate.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTexLookupVerifier.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTexCompareVerifier.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "qpWatchDog.h"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gls
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace TextureTestUtil
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulosenum
54b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos{
55b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos	MIN_SUBPIXEL_BITS	= 4
56b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos};
57b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
583c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySamplerType getSamplerType (tcu::TextureFormat format)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::TextureFormat;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (format.type)
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT8:
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT16:
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT32:
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_INT;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT8:
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT32:
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_1010102_REV:
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_UINT;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Texture formats used in depth/stencil textures.
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT16:
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_24_8:
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FLOAT : SAMPLERTYPE_UINT;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FLOAT;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySamplerType getFetchSamplerType (tcu::TextureFormat format)
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::TextureFormat;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (format.type)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT8:
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT16:
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT32:
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FETCH_INT;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT8:
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT32:
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_1010102_REV:
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FETCH_UINT;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Texture formats used in depth/stencil textures.
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT16:
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_24_8:
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FETCH_FLOAT : SAMPLERTYPE_FETCH_UINT;
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FETCH_FLOAT;
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Texture1DView getSubView (const tcu::Texture1DView& view, int baseLevel, int maxLevel)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Texture1DView(numLevels, view.getLevels()+clampedBase);
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Texture2DView getSubView (const tcu::Texture2DView& view, int baseLevel, int maxLevel)
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Texture2DView(numLevels, view.getLevels()+clampedBase);
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::TextureCubeView getSubView (const tcu::TextureCubeView& view, int baseLevel, int maxLevel)
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int							clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int							clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int							numLevels	= clampedMax-clampedBase+1;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::ConstPixelBufferAccess*	levels[tcu::CUBEFACE_LAST];
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		levels[face] = view.getFaceLevels((tcu::CubeFace)face) + clampedBase;
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::TextureCubeView(numLevels, levels);
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Texture3DView getSubView (const tcu::Texture3DView& view, int baseLevel, int maxLevel)
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Texture3DView(numLevels, view.getLevels()+clampedBase);
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrystatic tcu::TextureCubeArrayView getSubView (const tcu::TextureCubeArrayView& view, int baseLevel, int maxLevel)
1488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
1498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return tcu::TextureCubeArrayView(numLevels, view.getLevels()+clampedBase);
1538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
1548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float linearInterpolate (float t, float minVal, float maxVal)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return minVal + (maxVal - minVal) * t;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::Vec4 linearInterpolate (float t, const tcu::Vec4& a, const tcu::Vec4& b)
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return a + (b - a) * t;
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float bilinearInterpolate (float x, float y, const tcu::Vec4& quad)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w00 = (1.0f-x)*(1.0f-y);
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w01 = (1.0f-x)*y;
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w10 = x*(1.0f-y);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w11 = x*y;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return quad.x()*w00 + quad.y()*w10 + quad.z()*w01 + quad.w()*w11;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float triangleInterpolate (float v0, float v1, float v2, float x, float y)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return v0 + (v2-v0)*x + (v1-v0)*y;
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float triangleInterpolate (const tcu::Vec3& v, float x, float y)
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return triangleInterpolate(v.x(), v.y(), v.z(), x, y);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float triQuadInterpolate (float x, float y, const tcu::Vec4& quad)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Top left fill rule.
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (x + y < 1.0f)
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return triangleInterpolate(quad.x(), quad.y(), quad.z(), x, y);
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return triangleInterpolate(quad.w(), quad.z(), quad.y(), 1.0f-x, 1.0f-y);
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySurfaceAccess::SurfaceAccess (tcu::Surface& surface, const tcu::PixelFormat& colorFmt, int x, int y, int width, int height)
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_surface		(&surface)
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colorMask	(getColorMask(colorFmt))
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_x			(x)
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_y			(y)
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width		(width)
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height		(height)
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2033c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySurfaceAccess::SurfaceAccess (tcu::Surface& surface, const tcu::PixelFormat& colorFmt)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_surface		(&surface)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colorMask	(getColorMask(colorFmt))
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_x			(0)
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_y			(0)
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width		(surface.getWidth())
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height		(surface.getHeight())
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySurfaceAccess::SurfaceAccess (const SurfaceAccess& parent, int x, int y, int width, int height)
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_surface			(parent.m_surface)
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colorMask		(parent.m_colorMask)
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_x				(parent.m_x + x)
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_y				(parent.m_y + y)
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width			(width)
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height			(height)
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 1D lookup LOD computation.
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float computeLodFromDerivates (LodMode mode, float dudx, float dudy)
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float p = 0.0f;
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note [mika] Min and max bounds equal to exact with 1D textures
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_EXACT:
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MIN_BOUND:
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MAX_BOUND:
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(p);
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, deInt32 srcSize, const tcu::Vec3& sq)
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dux	= (sq.z() - sq.x()) * (float)srcSize;
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float duy	= (sq.y() - sq.x()) * (float)srcSize;
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dx	= (float)dstSize.x();
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dy	= (float)dstSize.y();
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dux/dx, duy/dy);
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 2D lookup LOD computation.
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dudy, float dvdy)
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float p = 0.0f;
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_EXACT:
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx), deFloatSqrt(dudy*dudy + dvdy*dvdy));
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MIN_BOUND:
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MAX_BOUND:
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = mode == LODMODE_MIN_BOUND ? de::max(mu, mv) : mu + mv;
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(p);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, const tcu::IVec2& srcSize, const tcu::Vec3& sq, const tcu::Vec3& tq)
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dux	= (sq.z() - sq.x()) * (float)srcSize.x();
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float duy	= (sq.y() - sq.x()) * (float)srcSize.x();
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvx	= (tq.z() - tq.x()) * (float)srcSize.y();
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvy	= (tq.y() - tq.x()) * (float)srcSize.y();
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dx	= (float)dstSize.x();
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dy	= (float)dstSize.y();
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dux/dx, dvx/dx, duy/dy, dvy/dy);
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 3D lookup LOD computation.
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dwdx, float dudy, float dvdy, float dwdy)
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float p = 0.0f;
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_EXACT:
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx + dwdx*dwdx), deFloatSqrt(dudy*dudy + dvdy*dvdy + dwdy*dwdy));
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MIN_BOUND:
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MAX_BOUND:
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mw = de::max(deFloatAbs(dwdx), deFloatAbs(dwdy));
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = mode == LODMODE_MIN_BOUND ? de::max(de::max(mu, mv), mw) : (mu + mv + mw);
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(p);
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, const tcu::IVec3& srcSize, const tcu::Vec3& sq, const tcu::Vec3& tq, const tcu::Vec3& rq)
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dux	= (sq.z() - sq.x()) * (float)srcSize.x();
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float duy	= (sq.y() - sq.x()) * (float)srcSize.x();
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvx	= (tq.z() - tq.x()) * (float)srcSize.y();
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvy	= (tq.y() - tq.x()) * (float)srcSize.y();
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwx	= (rq.z() - rq.x()) * (float)srcSize.z();
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwy	= (rq.y() - rq.x()) * (float)srcSize.z();
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dx	= (float)dstSize.x();
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dy	= (float)dstSize.y();
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dux/dx, dvx/dx, dwx/dx, duy/dy, dvy/dy, dwy/dy);
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny)
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (s[0]*(1.0f-nx-ny)/w[0] + s[1]*ny/w[1] + s[2]*nx/w[2]) / ((1.0f-nx-ny)/w[0] + ny/w[1] + nx/w[2]);
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float triDerivateX (const tcu::Vec3& s, const tcu::Vec3& w, float wx, float width, float ny)
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float d = w[1]*w[2]*(width*(ny - 1.0f) + wx) - w[0]*(w[2]*width*ny + w[1]*wx);
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (w[0]*w[1]*w[2]*width * (w[1]*(s[0] - s[2])*(ny - 1.0f) + ny*(w[2]*(s[1] - s[0]) + w[0]*(s[2] - s[1])))) / (d*d);
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float triDerivateY (const tcu::Vec3& s, const tcu::Vec3& w, float wy, float height, float nx)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float d = w[1]*w[2]*(height*(nx - 1.0f) + wy) - w[0]*(w[1]*height*nx + w[2]*wy);
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (w[0]*w[1]*w[2]*height * (w[2]*(s[0] - s[1])*(nx - 1.0f) + nx*(w[0]*(s[1] - s[2]) + w[1]*(s[2] - s[0])))) / (d*d);
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 1D lookup LOD.
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& projection, float wx, float wy, float width, float height)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Exact derivatives.
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dudx, dudy);
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 2D lookup LOD.
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& v, const tcu::Vec3& projection, float wx, float wy, float width, float height)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Exact derivatives.
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdx	= triDerivateX(v, projection, wx, width, wy/height);
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdy	= triDerivateY(v, projection, wy, height, wx/width);
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dudx, dvdx, dudy, dvdy);
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 3D lookup LOD.
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& v, const tcu::Vec3& w, const tcu::Vec3& projection, float wx, float wy, float width, float height)
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Exact derivatives.
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdx	= triDerivateX(v, projection, wx, width, wy/height);
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdx	= triDerivateX(w, projection, wx, width, wy/height);
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdy	= triDerivateY(v, projection, wy, height, wx/width);
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdy	= triDerivateY(w, projection, wy, height, wx/width);
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dudx, dvdx, dwdx, dudy, dvdy, dwdy);
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture1DView& src, const ReferenceParams& params, float s, float lod)
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, lod), 0.0, 0.0, 1.0f);
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, lod);
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture2DView& src, const ReferenceParams& params, float s, float t, float lod)
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f);
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, lod);
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::TextureCubeView& src, const ReferenceParams& params, float s, float t, float r, float lod)
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f);
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, r, lod);
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture2DArrayView& src, const ReferenceParams& params, float s, float t, float r, float lod)
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f);
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, r, lod);
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::TextureCubeArrayView& src, const ReferenceParams& params, float s, float t, float r, float q, float lod)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, q, lod), 0.0, 0.0, 1.0f);
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, r, q, lod);
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture1DArrayView& src, const ReferenceParams& params, float s, float t, float lod)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f);
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, lod);
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DView& src, const tcu::Vec4& sq, const ReferenceParams& params)
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			srcSize		= src.getWidth();
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		triLod[2]	= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias, params.minLod, params.maxLod),
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias, params.minLod, params.maxLod) };
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, lod) * params.colorScale + params.colorBias, x, y);
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	srcSize		= tcu::IVec2(src.getWidth(), src.getHeight());
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		triLod[2]	= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod),
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) };
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y);
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture1DView& src, const tcu::Vec4& sq, const ReferenceParams& params)
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		dstW		= (float)dst.getWidth();
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		dstH		= (float)dst.getHeight();
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4	uq			= sq * (float)src.getWidth();
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triU[2]		= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triW[2]		= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wx		= (float)px + 0.5f;
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wy		= (float)py + 0.5f;
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	nx		= wx / dstW;
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	ny		= wy / dstH;
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWx	= triNdx ? dstW - wx : wx;
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWy	= triNdx ? dstH - wy : wy;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNx	= triNdx ? 1.0f - nx : nx;
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNy	= triNdx ? 1.0f - ny : ny;
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							+ lodBias;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, lod) * params.colorScale + params.colorBias, px, py);
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture2DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		dstW		= (float)dst.getWidth();
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		dstH		= (float)dst.getHeight();
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4	uq			= sq * (float)src.getWidth();
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4	vq			= tq * (float)src.getHeight();
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triU[2]		= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triV[2]		= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triW[2]		= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wx		= (float)px + 0.5f;
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wy		= (float)py + 0.5f;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	nx		= wx / dstW;
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	ny		= wy / dstH;
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWx	= triNdx ? dstW - wx : wx;
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWy	= triNdx ? dstH - wy : wy;
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNx	= triNdx ? 1.0f - nx : nx;
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNy	= triNdx ? 1.0f - ny : ny;
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy);
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							+ lodBias;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, px, py);
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture2DView& src, const float* texCoord, const ReferenceParams& params)
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture2DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & ReferenceParams::PROJECTED)
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureProjected(dst, view, sq, tq, params);
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureNonProjected(dst, view, sq, tq, params);
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture1DView& src, const float* texCoord, const ReferenceParams& params)
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture1DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & ReferenceParams::PROJECTED)
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureProjected(dst, view, sq, params);
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureNonProjected(dst, view, sq, params);
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeCubeLodFromDerivates (LodMode lodMode, const tcu::Vec3& coord, const tcu::Vec3& coordDx, const tcu::Vec3& coordDy, const int faceSize)
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::CubeFace	face	= tcu::selectCubeFace(coord);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					maNdx	= 0;
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					sNdx	= 0;
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					tNdx	= 0;
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Derivate signs don't matter when computing lod
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X:
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y:
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break;
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z:
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break;
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		sc		= coord[sNdx];
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		tc		= coord[tNdx];
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		ma		= de::abs(coord[maNdx]);
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		scdx	= coordDx[sNdx];
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		tcdx	= coordDx[tNdx];
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		madx	= de::abs(coordDx[maNdx]);
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		scdy	= coordDy[sNdx];
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		tcdy	= coordDy[tNdx];
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		mady	= de::abs(coordDy[maNdx]);
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dudx	= float(faceSize) * 0.5f * (scdx*ma - sc*madx) / (ma*ma);
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dvdx	= float(faceSize) * 0.5f * (tcdx*ma - tc*madx) / (ma*ma);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dudy	= float(faceSize) * 0.5f * (scdy*ma - sc*mady) / (ma*ma);
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dvdy	= float(faceSize) * 0.5f * (tcdy*ma - tc*mady) / (ma*ma);
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return computeLodFromDerivates(lodMode, dudx, dvdx, dudy, dvdy);
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(dst.getWidth(), dst.getHeight());
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			srcSize			= src.getSize();
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			lodBias			((params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wx		= (float)px + 0.5f;
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wy		= (float)py + 0.5f;
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		nx		= wx / dstW;
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		ny		= wy / dstH;
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNx	= triNdx ? 1.0f - nx : nx;
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNy	= triNdx ? 1.0f - ny : ny;
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coord		(triangleInterpolate(triS[triNdx], triNx, triNy),
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triangleInterpolate(triT[triNdx], triNx, triNy),
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triangleInterpolate(triR[triNdx], triNx, triNy));
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		lod			= de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, srcSize) + lodBias, params.minLod, params.maxLod);
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), lod) * params.colorScale + params.colorBias, px, py);
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeView& src, const float* texCoord, const ReferenceParams& params)
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureCubeView	view	= getSubView(src, params.baseLevel, params.maxLevel);
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				rq		= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sampleTexture(dst, view, sq, tq, rq, params);
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2013-07-17 pyry] Remove this!
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTextureMultiFace (const SurfaceAccess& dst, const tcu::TextureCubeView& src, const float* texCoord, const ReferenceParams& params)
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sampleTexture(dst, src, texCoord, params);
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DArrayView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	srcSize		= tcu::IVec2(src.getWidth(), src.getHeight());
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triR[2]		= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		triLod[2]	= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias,
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias};
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	r		= triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY);
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, r, lod) * params.colorScale + params.colorBias, x, y);
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture2DArrayView& src, const float* texCoord, const ReferenceParams& params)
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2012-02-17 pyry] Support projected lookups.
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTextureNonProjected(dst, src, sq, tq, rq, params);
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DArrayView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32		srcSize		= src.getWidth();
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		triLod[2]	= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias,
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias};
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y);
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture1DArrayView& src, const float* texCoord, const ReferenceParams& params)
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2014-06-09 mika] Support projected lookups.
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTextureNonProjected(dst, src, sq, tq, params);
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture3DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::IVec3	srcSize		= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triR[2]		= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		triLod[2]	= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias, params.minLod, params.maxLod),
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry								de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias, params.minLod, params.maxLod) };
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	r		= triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY);
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, x, y);
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture3DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		dstW		= (float)dst.getWidth();
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		dstH		= (float)dst.getHeight();
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4	uq			= sq * (float)src.getWidth();
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4	vq			= tq * (float)src.getHeight();
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4	wq			= rq * (float)src.getDepth();
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triR[2]		= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triU[2]		= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triV[2]		= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triW[2]		= { wq.swizzle(0, 1, 2), wq.swizzle(3, 2, 1) };
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3	triP[2]		= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wx		= (float)px + 0.5f;
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wy		= (float)py + 0.5f;
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	nx		= wx / dstW;
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	ny		= wy / dstH;
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWx	= triNdx ? dstW - wx : wx;
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWy	= triNdx ? dstH - wy : wy;
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNx	= triNdx ? 1.0f - nx : nx;
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNy	= triNdx ? 1.0f - ny : ny;
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= projectedTriInterpolate(triS[triNdx], triP[triNdx], triNx, triNy);
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= projectedTriInterpolate(triT[triNdx], triP[triNdx], triNx, triNy);
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	r		= projectedTriInterpolate(triR[triNdx], triP[triNdx], triNx, triNy);
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triP[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							+ lodBias;
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, px, py);
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture3DView& src, const float* texCoord, const ReferenceParams& params)
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture3DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				rq		= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & ReferenceParams::PROJECTED)
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureProjected(dst, view, sq, tq, rq, params);
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureNonProjected(dst, view, sq, tq, rq, params);
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeArrayView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const tcu::Vec4& qq, const ReferenceParams& params)
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstW	= (float)dst.getWidth();
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstH	= (float)dst.getHeight();
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3		triS[2]	= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3		triT[2]	= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3		triR[2]	= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3		triQ[2]	= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3	triW[2]	= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		lodBias	= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wx		= (float)px + 0.5f;
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wy		= (float)py + 0.5f;
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		nx		= wx / dstW;
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		ny		= wy / dstH;
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNx	= triNdx ? 1.0f - nx : nx;
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNy	= triNdx ? 1.0f - ny : ny;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coord	(triangleInterpolate(triS[triNdx], triNx, triNy),
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triangleInterpolate(triT[triNdx], triNx, triNy),
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triangleInterpolate(triR[triNdx], triNx, triNy));
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		coordQ	= triangleInterpolate(triQ[triNdx], triNx, triNy);
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDx	(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDy	(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const float		lod		= de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, src.getSize()) + lodBias, params.minLod, params.maxLod);
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), coordQ, lod) * params.colorScale + params.colorBias, px, py);
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeArrayView& src, const float* texCoord, const ReferenceParams& params)
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 qq = tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(dst, src, sq, tq, rq, qq, params);
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid fetchTexture (const SurfaceAccess& dst, const tcu::ConstPixelBufferAccess& src, const float* texCoord, const tcu::Vec4& colorScale, const tcu::Vec4& colorBias)
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq			= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	triX	= triNdx ? 1.0f-xf : xf;
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	triY	= triNdx ? 1.0f-yf : yf;
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(src.getPixel((int)s, 0) * colorScale + colorBias, x, y);
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid clear (const SurfaceAccess& dst, const tcu::Vec4& color)
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(color, x, y);
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareImages (TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold)
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::pixelThresholdCompare(log, "Result", "Image comparison result", reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareImages (TestLog& log, const char* name, const char* desc, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold)
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::pixelThresholdCompare(log, name, desc, reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint measureAccuracy (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, int bestScoreDiff, int worstScoreDiff)
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::measurePixelDiffAccuracy(log, "Result", "Image comparison result", reference, rendered, bestScoreDiff, worstScoreDiff, tcu::COMPARE_LOG_EVERYTHING);
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int rangeDiff (int x, int a, int b)
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (x < a)
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return a-x;
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (x > b)
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return x-b;
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::RGBA rangeDiff (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b)
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int rMin = de::min(a.getRed(),		b.getRed());
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int rMax = de::max(a.getRed(),		b.getRed());
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int gMin = de::min(a.getGreen(),	b.getGreen());
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int gMax = de::max(a.getGreen(),	b.getGreen());
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int bMin = de::min(a.getBlue(),		b.getBlue());
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int bMax = de::max(a.getBlue(),		b.getBlue());
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int aMin = de::min(a.getAlpha(),	b.getAlpha());
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int aMax = de::max(a.getAlpha(),	b.getAlpha());
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::RGBA(rangeDiff(p.getRed(),		rMin, rMax),
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 rangeDiff(p.getGreen(),	gMin, gMax),
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 rangeDiff(p.getBlue(),		bMin, bMax),
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 rangeDiff(p.getAlpha(),	aMin, aMax));
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool rangeCompare (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b, tcu::RGBA threshold)
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::RGBA diff = rangeDiff(p, a, b);
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return diff.getRed()	<= threshold.getRed() &&
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   diff.getGreen()	<= threshold.getGreen() &&
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   diff.getBlue()	<= threshold.getBlue() &&
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   diff.getAlpha()	<= threshold.getAlpha();
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10193c827367444ee418f129b2c238299f49d3264554Jarkko PoyryRandomViewport::RandomViewport (const tcu::RenderTarget& renderTarget, int preferredWidth, int preferredHeight, deUint32 seed)
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: x			(0)
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, y			(0)
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, width		(deMin32(preferredWidth, renderTarget.getWidth()))
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, height	(deMin32(preferredHeight, renderTarget.getHeight()))
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random rnd(seed);
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	x = rnd.getInt(0, renderTarget.getWidth()	- width);
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	y = rnd.getInt(0, renderTarget.getHeight()	- height);
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10303c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramLibrary::ProgramLibrary (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision)
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_context				(context)
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_testCtx				(testCtx)
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_glslVersion			(glslVersion)
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_texCoordPrecision	(texCoordPrecision)
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10383c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramLibrary::~ProgramLibrary (void)
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	clear();
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ProgramLibrary::clear (void)
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (map<Program, glu::ShaderProgram*>::iterator i = m_programs.begin(); i != m_programs.end(); i++)
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete i->second;
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		i->second = DE_NULL;
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_programs.clear();
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram* ProgramLibrary::getProgram (Program program)
10543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog& log = m_testCtx.getLog();
10563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_programs.find(program) != m_programs.end())
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_programs[program]; // Return from cache.
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* vertShaderTemplate =
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_HEADER}"
10623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_IN} highp vec4 a_position;\n"
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_IN} ${PRECISION} ${TEXCOORD_TYPE} a_texCoord;\n"
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_OUT} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n"
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main (void)\n"
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	gl_Position = a_position;\n"
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	v_texCoord = a_texCoord;\n"
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* fragShaderTemplate =
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${FRAG_HEADER}"
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${FRAG_IN} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n"
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} float u_bias;\n"
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} float u_ref;\n"
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} vec4 u_colorScale;\n"
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} vec4 u_colorBias;\n"
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} ${SAMPLER_TYPE} u_sampler;\n"
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main (void)\n"
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	${FRAG_COLOR} = ${LOOKUP} * u_colorScale + u_colorBias;\n"
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string> params;
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	isCube		= de::inRange<int>(program, PROGRAM_CUBE_FLOAT, PROGRAM_CUBE_SHADOW_BIAS);
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	isArray		= de::inRange<int>(program, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_2D_ARRAY_SHADOW)
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_1D_ARRAY_FLOAT, PROGRAM_1D_ARRAY_SHADOW);
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	is1D		= de::inRange<int>(program, PROGRAM_1D_FLOAT, PROGRAM_1D_UINT_BIAS)
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_1D_ARRAY_FLOAT, PROGRAM_1D_ARRAY_SHADOW)
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_BUFFER_FLOAT, PROGRAM_BUFFER_UINT);
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	is2D		= de::inRange<int>(program, PROGRAM_2D_FLOAT, PROGRAM_2D_UINT_BIAS)
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_2D_ARRAY_SHADOW);
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	is3D		= de::inRange<int>(program, PROGRAM_3D_FLOAT, PROGRAM_3D_UINT_BIAS);
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	isCubeArray	= de::inRange<int>(program, PROGRAM_CUBE_ARRAY_FLOAT, PROGRAM_CUBE_ARRAY_SHADOW);
11008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	bool	isBuffer	= de::inRange<int>(program, PROGRAM_BUFFER_FLOAT, PROGRAM_BUFFER_UINT);
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_glslVersion == glu::GLSL_VERSION_100_ES)
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_HEADER"]	= "";
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_HEADER"]	= "";
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_IN"]		= "attribute";
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_OUT"]		= "varying";
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_IN"]		= "varying";
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_COLOR"]	= "gl_FragColor";
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_glslVersion == glu::GLSL_VERSION_300_ES || m_glslVersion == glu::GLSL_VERSION_310_ES || m_glslVersion == glu::GLSL_VERSION_330)
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const string	version	= glu::getGLSLVersionDeclaration(m_glslVersion);
11148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const char*		ext		= DE_NULL;
11158852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
11168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (isCubeArray && glu::glslVersionIsES(m_glslVersion))
11178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			ext = "GL_EXT_texture_cube_map_array";
11188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else if (isBuffer && glu::glslVersionIsES(m_glslVersion))
11198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			ext = "GL_EXT_texture_buffer";
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		params["FRAG_HEADER"]	= version + (ext ? string("\n#extension ") + ext + " : require" : string()) + "\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
11228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		params["VTX_HEADER"]	= version + "\n";
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_IN"]		= "in";
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_OUT"]		= "out";
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_IN"]		= "in";
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_COLOR"]	= "dEQP_FragColor";
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!"Unsupported version");
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params["PRECISION"]		= glu::getPrecisionName(m_texCoordPrecision);
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isCubeArray)
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "vec4";
11353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isCube || (is2D && isArray) || is3D)
11363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "vec3";
11373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if ((is1D && isArray) || is2D)
11383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "vec2";
11393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (is1D)
11403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "float";
11413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
11433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*	sampler	= DE_NULL;
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*	lookup	= DE_NULL;
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_glslVersion == glu::GLSL_VERSION_300_ES || m_glslVersion == glu::GLSL_VERSION_310_ES || m_glslVersion == glu::GLSL_VERSION_330)
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (program)
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT:			sampler = "sampler2D";				lookup = "texture(u_sampler, v_texCoord)";												break;
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_INT:			sampler = "isampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_UINT:			sampler = "usampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_SHADOW:			sampler = "sampler2DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT_BIAS:		sampler = "sampler2D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_INT_BIAS:		sampler = "isampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_UINT_BIAS:		sampler = "usampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_SHADOW_BIAS:	sampler = "sampler2DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)";	break;
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_FLOAT:			sampler = "sampler1D";				lookup = "texture(u_sampler, v_texCoord)";												break;
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_INT:			sampler = "isampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_UINT:			sampler = "usampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_SHADOW:			sampler = "sampler1DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_FLOAT_BIAS:		sampler = "sampler1D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_INT_BIAS:		sampler = "isampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_UINT_BIAS:		sampler = "usampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_SHADOW_BIAS:	sampler = "sampler1DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)";	break;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT:		sampler = "samplerCube";			lookup = "texture(u_sampler, v_texCoord)";												break;
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_INT:			sampler = "isamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_UINT:			sampler = "usamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_SHADOW:		sampler = "samplerCubeShadow";		lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT_BIAS:	sampler = "samplerCube";			lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_INT_BIAS:		sampler = "isamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_UINT_BIAS:	sampler = "usamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_SHADOW_BIAS:	sampler = "samplerCubeShadow";		lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)";	break;
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_ARRAY_FLOAT:	sampler = "sampler2DArray";			lookup = "texture(u_sampler, v_texCoord)";												break;
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_ARRAY_INT:		sampler = "isampler2DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_ARRAY_UINT:		sampler = "usampler2DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_ARRAY_SHADOW:	sampler = "sampler2DArrayShadow";	lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_FLOAT:			sampler = "sampler3D";				lookup = "texture(u_sampler, v_texCoord)";												break;
11803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_INT:			sampler = "isampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_UINT:			sampler =" usampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_FLOAT_BIAS:		sampler = "sampler3D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_INT_BIAS:		sampler = "isampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_UINT_BIAS:		sampler =" usampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_ARRAY_FLOAT:	sampler = "samplerCubeArray";		lookup = "texture(u_sampler, v_texCoord)";												break;
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_ARRAY_INT:	sampler = "isamplerCubeArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_ARRAY_UINT:	sampler = "usamplerCubeArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_ARRAY_SHADOW:	sampler = "samplerCubeArrayShadow";	lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_ARRAY_FLOAT:	sampler = "sampler1DArray";			lookup = "texture(u_sampler, v_texCoord)";												break;
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_ARRAY_INT:		sampler = "isampler1DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_ARRAY_UINT:		sampler = "usampler1DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_ARRAY_SHADOW:	sampler = "sampler1DArrayShadow";	lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_BUFFER_FLOAT:		sampler = "samplerBuffer";			lookup = "texelFetch(u_sampler, int(v_texCoord))";										break;
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_BUFFER_INT:		sampler = "isamplerBuffer";			lookup = "vec4(texelFetch(u_sampler, int(v_texCoord)))";								break;
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_BUFFER_UINT:		sampler = "usamplerBuffer";			lookup = "vec4(texelFetch(u_sampler, int(v_texCoord)))";								break;
11963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_glslVersion == glu::GLSL_VERSION_100_ES)
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampler = isCube ? "samplerCube" : "sampler2D";
12033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (program)
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT:			lookup = "texture2D(u_sampler, v_texCoord)";			break;
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT_BIAS:		lookup = "texture2D(u_sampler, v_texCoord, u_bias)";	break;
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT:		lookup = "textureCube(u_sampler, v_texCoord)";			break;
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT_BIAS:	lookup = "textureCube(u_sampler, v_texCoord, u_bias)";	break;
12103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!"Unsupported version");
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params["SAMPLER_TYPE"]	= sampler;
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params["LOOKUP"]		= lookup;
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string vertSrc = tcu::StringTemplate(vertShaderTemplate).specialize(params);
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string fragSrc = tcu::StringTemplate(fragShaderTemplate).specialize(params);
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram* progObj = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(vertSrc, fragSrc));
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!progObj->isOk())
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << *progObj;
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete progObj;
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Failed to compile shader program");
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_programs[program] = progObj;
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (...)
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete progObj;
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return progObj;
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12443c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureRenderer::TextureRenderer (const glu::RenderContext& context, tcu::TestContext& testCtx, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision)
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_renderCtx		(context)
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_testCtx			(testCtx)
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_programLibrary	(context, testCtx, glslVersion, texCoordPrecision)
12483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12513c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureRenderer::~TextureRenderer (void)
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	clear();
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureRenderer::clear (void)
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_programLibrary.clear();
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureRenderer::renderQuad (int texUnit, const float* texCoord, TextureType texType)
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	renderQuad(texUnit, texCoord, RenderParams(texType));
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureRenderer::renderQuad (int texUnit, const float* texCoord, const RenderParams& params)
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl			= m_renderCtx.getFunctions();
12693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4				wCoord		= params.flags & RenderParams::PROJECTED ? params.w : tcu::Vec4(1.0f);
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useBias		= !!(params.flags & RenderParams::USE_BIAS);
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TestLog&				log			= m_testCtx.getLog();
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					logUniforms	= !!(params.flags & RenderParams::LOG_UNIFORMS);
12733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render quad with texture.
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float position[] =
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f*wCoord.x(), -1.0f*wCoord.x(), 0.0f, wCoord.x(),
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f*wCoord.y(), +1.0f*wCoord.y(), 0.0f, wCoord.y(),
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f*wCoord.z(), -1.0f*wCoord.z(), 0.0f, wCoord.z(),
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f*wCoord.w(), +1.0f*wCoord.w(), 0.0f, wCoord.w()
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Program progSpec	= PROGRAM_LAST;
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		numComps	= 0;
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.texType == TEXTURETYPE_2D)
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 2;
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_2D_FLOAT_BIAS	: PROGRAM_2D_FLOAT;		break;
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_2D_INT_BIAS	: PROGRAM_2D_INT;		break;
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_2D_UINT_BIAS	: PROGRAM_2D_UINT;		break;
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_2D_SHADOW_BIAS	: PROGRAM_2D_SHADOW;	break;
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_1D)
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 1;
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_1D_FLOAT_BIAS	: PROGRAM_1D_FLOAT;		break;
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_1D_INT_BIAS	: PROGRAM_1D_INT;		break;
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_1D_UINT_BIAS	: PROGRAM_1D_UINT;		break;
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_1D_SHADOW_BIAS	: PROGRAM_1D_SHADOW;	break;
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_CUBE)
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 3;
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_CUBE_FLOAT_BIAS	: PROGRAM_CUBE_FLOAT;	break;
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_CUBE_INT_BIAS		: PROGRAM_CUBE_INT;		break;
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_CUBE_UINT_BIAS		: PROGRAM_CUBE_UINT;	break;
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_CUBE_SHADOW_BIAS	: PROGRAM_CUBE_SHADOW;	break;
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_3D)
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 3;
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_3D_FLOAT_BIAS	: PROGRAM_3D_FLOAT;		break;
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_3D_INT_BIAS	: PROGRAM_3D_INT;		break;
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_3D_UINT_BIAS	: PROGRAM_3D_UINT;		break;
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_2D_ARRAY)
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 3;
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_2D_ARRAY_FLOAT;	break;
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = PROGRAM_2D_ARRAY_INT;	break;
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_2D_ARRAY_UINT;	break;
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_2D_ARRAY_SHADOW;	break;
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_CUBE_ARRAY)
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!useBias);
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 4;
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_CUBE_ARRAY_FLOAT;	break;
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = PROGRAM_CUBE_ARRAY_INT;		break;
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_CUBE_ARRAY_UINT;		break;
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_CUBE_ARRAY_SHADOW;	break;
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_1D_ARRAY)
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 2;
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_1D_ARRAY_FLOAT;	break;
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = PROGRAM_1D_ARRAY_INT;	break;
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_1D_ARRAY_UINT;	break;
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_1D_ARRAY_SHADOW;	break;
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_BUFFER)
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 1;
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FETCH_FLOAT:	progSpec = PROGRAM_BUFFER_FLOAT;	break;
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FETCH_INT:		progSpec = PROGRAM_BUFFER_INT;		break;
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FETCH_UINT:	progSpec = PROGRAM_BUFFER_UINT;		break;
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:						DE_ASSERT(false);
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram* program = m_programLibrary.getProgram(progSpec);
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2012-09-26 pyry] Move to ProgramLibrary and log unique programs only(?)
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & RenderParams::LOG_PROGRAMS)
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << *program;
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Set vertex attributes");
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Program and uniforms.
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 prog = program->getProgram();
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(prog);
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform1i(gl.getUniformLocation(prog, "u_sampler"), texUnit);
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (logUniforms)
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "u_sampler = " << texUnit << TestLog::EndMessage;
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useBias)
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(prog, "u_bias"), params.bias);
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (logUniforms)
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "u_bias = " << params.bias << TestLog::EndMessage;
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(prog, "u_ref"), params.ref);
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (logUniforms)
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "u_ref = " << params.ref << TestLog::EndMessage;
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform4fv(gl.getUniformLocation(prog, "u_colorScale"),	1, params.colorScale.getPtr());
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform4fv(gl.getUniformLocation(prog, "u_colorBias"),	1, params.colorBias.getPtr());
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (logUniforms)
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "u_colorScale = " << params.colorScale << TestLog::EndMessage;
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "u_colorBias = " << params.colorBias << TestLog::EndMessage;
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Set program state");
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding vertexArrays[] =
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("a_position",	4,			4, 0, &position[0]),
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("a_texCoord",	numComps,	4, 0, texCoord)
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_renderCtx, prog, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
14453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord1D (std::vector<float>& dst, float left, float right)
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4);
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = left;
14543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[1] = left;
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = right;
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = right;
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord1DArray (std::vector<float>& dst, int layerNdx, float left, float right)
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*2);
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = left;	dst[1] = (float)layerNdx;
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = left;	dst[3] = (float)layerNdx;
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[4] = right;	dst[5] = (float)layerNdx;
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = right;	dst[7] = (float)layerNdx;
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord2D (std::vector<float>& dst, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*2);
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = bottomLeft.x();	dst[1] = bottomLeft.y();
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = bottomLeft.x();	dst[3] = topRight.y();
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[4] = topRight.x();		dst[5] = bottomLeft.y();
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = topRight.x();		dst[7] = topRight.y();
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord2DArray (std::vector<float>& dst, int layerNdx, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*3);
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = bottomLeft.x();	dst[ 1] = bottomLeft.y();	dst[ 2] = (float)layerNdx;
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = bottomLeft.x();	dst[ 4] = topRight.y();		dst[ 5] = (float)layerNdx;
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = topRight.x();		dst[ 7] = bottomLeft.y();	dst[ 8] = (float)layerNdx;
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9] = topRight.x();		dst[10] = topRight.y();		dst[11] = (float)layerNdx;
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord3D (std::vector<float>& dst, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::IVec3& dirSwz)
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f0 = tcu::Vec3(0.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f1 = tcu::Vec3(0.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f2 = tcu::Vec3(1.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f3 = tcu::Vec3(1.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v0 = p0 + (p1-p0)*f0;
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v1 = p0 + (p1-p0)*f1;
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v2 = p0 + (p1-p0)*f2;
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v3 = p0 + (p1-p0)*f3;
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*3);
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = v0.x(); dst[ 1] = v0.y(); dst[ 2] = v0.z();
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = v1.x(); dst[ 4] = v1.y(); dst[ 5] = v1.z();
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = v2.x(); dst[ 7] = v2.y(); dst[ 8] = v2.z();
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9] = v3.x(); dst[10] = v3.y(); dst[11] = v3.z();
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face)
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordNegX[] =
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, -1.0f,
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, -1.0f,
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f,  1.0f,
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f,  1.0f
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordPosX[] =
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f,  1.0f,  1.0f,
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f, -1.0f,  1.0f,
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f,  1.0f, -1.0f,
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f, -1.0f, -1.0f
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordNegY[] =
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f,  1.0f,
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, -1.0f,
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f,  1.0f,
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, -1.0f
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordPosY[] =
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, +1.0f, -1.0f,
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, +1.0f,  1.0f,
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, +1.0f, -1.0f,
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, +1.0f,  1.0f
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordNegZ[] =
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f,  1.0f, -1.0f,
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, -1.0f,
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, -1.0f,
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, -1.0f
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordPosZ[] =
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, +1.0f,
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, +1.0f,
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f,  1.0f, +1.0f,
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, +1.0f
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float*	texCoord		= DE_NULL;
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				texCoordSize	= DE_LENGTH_OF_ARRAY(texCoordNegX);
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X: texCoord = texCoordNegX; break;
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: texCoord = texCoordPosX; break;
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y: texCoord = texCoordNegY; break;
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: texCoord = texCoordPosY; break;
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z: texCoord = texCoordNegZ; break;
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: texCoord = texCoordPosZ; break;
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(texCoordSize);
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::copy(texCoord, texCoord+texCoordSize, dst.begin());
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		sRow		= 0;
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		tRow		= 0;
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		mRow		= 0;
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	sSign		= 1.0f;
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	tSign		= 1.0f;
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	mSign		= 1.0f;
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;				   tSign = -1.0f;	break;
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;				sSign = -1.0f; tSign = -1.0f;	break;
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;				   tSign = -1.0f;	break;
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;												break;
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;	break;
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;							   tSign = -1.0f;	break;
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(3*4);
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0+mRow] = mSign;
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3+mRow] = mSign;
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6+mRow] = mSign;
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9+mRow] = mSign;
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0+sRow] = sSign * bottomLeft.x();
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3+sRow] = sSign * bottomLeft.x();
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6+sRow] = sSign * topRight.x();
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9+sRow] = sSign * topRight.x();
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0+tRow] = tSign * bottomLeft.y();
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3+tRow] = tSign * topRight.y();
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6+tRow] = tSign * bottomLeft.y();
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9+tRow] = tSign * topRight.y();
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid computeQuadTexCoordCubeArray (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight, const tcu::Vec2& layerRange)
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			sRow	= 0;
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			tRow	= 0;
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			mRow	= 0;
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	qRow	= 3;
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		sSign	= 1.0f;
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		tSign	= 1.0f;
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		mSign	= 1.0f;
16238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const float	l0		= layerRange.x();
16248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const float	l1		= layerRange.y();
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;				   tSign = -1.0f;	break;
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;				sSign = -1.0f; tSign = -1.0f;	break;
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;				   tSign = -1.0f;	break;
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;												break;
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;	break;
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;							   tSign = -1.0f;	break;
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
16353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*4);
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 0+mRow] = mSign;
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 4+mRow] = mSign;
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 8+mRow] = mSign;
16443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[12+mRow] = mSign;
16453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 0+sRow] = sSign * bottomLeft.x();
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 4+sRow] = sSign * bottomLeft.x();
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 8+sRow] = sSign * topRight.x();
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[12+sRow] = sSign * topRight.x();
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 0+tRow] = tSign * bottomLeft.y();
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 4+tRow] = tSign * topRight.y();
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 8+tRow] = tSign * bottomLeft.y();
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[12+tRow] = tSign * topRight.y();
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (l0 != l1)
16578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
16588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 0+qRow] = l0;
16598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 4+qRow] = l0*0.5f + l1*0.5f;
16608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 8+qRow] = l0*0.5f + l1*0.5f;
16618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[12+qRow] = l1;
16628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
16638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	else
16648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
16658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 0+qRow] = l0;
16668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 4+qRow] = l0;
16678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 8+qRow] = l0;
16688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[12+qRow] = l0;
16698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Texture result verification
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
16773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
16783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture1DView&				baseView,
16793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
16803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
16813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
16823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
16833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
16843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
16863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
16873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture1DView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
16893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			srcSize			= src.getWidth();
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
17093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
17103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
17123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
17143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
17163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
17203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
17253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		coord		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		coordDx		= triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * float(srcSize);
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float 	coordDy		= triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * float(srcSize);
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec);
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDxo	= triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * float(srcSize);
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDyo	= triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * float(srcSize);
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO	= tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec);
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture2DView&				baseView,
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&					sampleParams,
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture2DView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
18043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
18123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
18133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
18153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
18163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
18183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
18203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
18243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
18263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
18283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo));
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture1DView&				src,
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture2DView&				src,
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::TextureCubeView&			baseView,
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureCubeView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			srcSize			= src.getSize();
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos	const float			posEps			= 1.0f / float((1<<MIN_SUBPIXEL_BITS) + 1);
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
19963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
19983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
20003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
20023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
20033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Not strictly allowed by spec, but implementations do this in practice.
20053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1, -1),
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1, +1),
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1, -1),
2008e8ef296162c99669d786b805a148b9a3e8ae5831Pyry Haulos		tcu::Vec2(+1, +1),
20093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
20103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
20173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
20303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		tri0	= nx + ny - posEps <= 1.0f;
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		tri1	= nx + ny + posEps >= 1.0f;
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			isOk	= false;
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(tri0 || tri1);
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Pixel can belong to either of the triangles if it lies close enough to the edge.
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triWx	= triNdx ? dstW - wx : wx;
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triWy	= triNdx ? dstH - wy : wy;
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triNx	= triNdx ? 1.0f - nx : nx;
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triNy	= triNdx ? 1.0f - ny : ny;
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
20543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
20553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Compute lod bounds across lodOffsets range.
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		nxo		= wxo/dstW;
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		nyo		= wyo/dstH;
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix))
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						isOk = true;
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::TextureCubeView&			src,
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTextureMultiFace(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
21413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture3DView&				baseView,
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture3DView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec3	srcSize			= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2172b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos	const float			posEps			= 1.0f / float((1<<MIN_SUBPIXEL_BITS) + 1);
2173b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
21753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
21793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
21803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
21823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
21833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
21853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
21893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
21903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
21913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
21933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
21953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
21963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2205b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				const bool		tri0	= nx + ny - posEps <= 1.0f;
2206b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				const bool		tri1	= nx + ny + posEps >= 1.0f;
22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2208b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				bool			isOk	= false;
22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2210b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				DE_ASSERT(tri0 || tri1);
22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2212b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				// Pixel can belong to either of the triangles if it lies close enough to the edge.
2213b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2215b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triWx	= triNdx ? dstW - wx : wx;
2216b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triWy	= triNdx ? dstH - wy : wy;
2217b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triNx	= triNdx ? 1.0f - nx : nx;
2218b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triNy	= triNdx ? 1.0f - ny : ny;
22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2220b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
2221b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
2222b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
2223b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec3	coordDx		= tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
2224b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
2225b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
2226b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec3	coordDy		= tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
2227b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
2228b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
22293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2230b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDx.z(), coordDy.x(), coordDy.y(), coordDy.z(), lodPrec);
22313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2232b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					// Compute lod bounds across lodOffsets range.
2233b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
2234b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					{
2235b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
2236b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
2237b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		nxo		= wxo/dstW;
2238b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		nyo		= wyo/dstH;
2239b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2240b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
2241b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos													 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
2242b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos													 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
2243b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const tcu::Vec3	coordDxo	= tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
2244b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
2245b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
2246b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const tcu::Vec3	coordDyo	= tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
2247b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
2248b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
2249b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDxo.z(), coordDyo.x(), coordDyo.y(), coordDyo.z(), lodPrec);
2250b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2251b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
2252b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
2253b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					}
2254b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2255b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
2256b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2257b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix))
2258b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					{
2259b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						isOk = true;
2260b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						break;
2261b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					}
2262b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				}
22633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
22653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
22663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
22673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
22683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
22693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
22743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
22753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
22773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
22783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture3DView&				src,
22793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
22803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
22813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
22823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
22973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture1DArrayView&		src,
23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			srcSize			= float(src.getWidth()); // For lod computation, thus #layers is ignored.
23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
23363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
23463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
23473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
23483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
23493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
23503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
23523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
23543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
23583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
23603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
23623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coord	(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float	coordDx		= triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * srcSize;
23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float	coordDy		= triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * srcSize;
23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec);
23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
23903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
23913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo));
23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDxo		= triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * srcSize;
23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDyo		= triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * srcSize;
23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec);
23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
24073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture2DArrayView&		src,
24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
24333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
24343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
24353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
24373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		srcSize			= tcu::IVec2(src.getWidth(), src.getHeight()).asFloat(); // For lod computation, thus #layers is ignored.
24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
24433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
24443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
24463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
24483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
24503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
24523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
24543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
24553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
24563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
24573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
24583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
24603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
24623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
24663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
24683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
24713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
24733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
24743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize;
24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize;
24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize;
25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize;
25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture1DArrayView&		src,
25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
25363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
25393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
25473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
25493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture2DArrayView&		src,
25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
25968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
25978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
25988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
25998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	log << TestLog::EndImageSet;
26008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return numFailedPixels == 0;
26028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
26038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
26058852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
26068852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
26078852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
26088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::TextureCubeArrayView&		baseView,
26098852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const float*							texCoord,
26108852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const ReferenceParams&				sampleParams,
26118852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
26128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::IVec4&						coordBits,
26138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
26148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  qpWatchDog*							watchDog)
26158852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
26168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
26178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
26188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::TextureCubeArrayView	src	= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
26208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// What is the 'q' in all these names? Also a two char name for something that is in scope for ~120 lines and only used twice each seems excessive
26228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
26238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
26248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
26258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec4		qq				= tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
26268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
26288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const float			dstW			= float(dstSize.x());
26298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const float			dstH			= float(dstSize.y());
26308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int			srcSize			= src.getSize();
26318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// Coordinates per triangle.
26338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
26348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
26358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
26368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec3		triQ[2]			= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
26378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
26388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
26408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const float			posEps			= 1.0f / float((1<<4) + 1); // ES3 requires at least 4 subpixel bits.
26428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	int					numFailed		= 0;
26448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
26468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
26478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(-1,  0),
26488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(+1,  0),
26498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2( 0, -1),
26508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2( 0, +1),
26518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// \note Not strictly allowed by spec, but implementations do this in practice.
26538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(-1, -1),
26548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(-1, +1),
26558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(+1, -1),
26562e736e5cc21486837e98cae3c9303751f9a15c79Pyry Haulos		tcu::Vec2(+1, +1),
26578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	};
26588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
26608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
26628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
26638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
26648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (watchDog)
26658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			qpWatchDog_touch(watchDog);
26668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
26688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
26698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
26708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
26718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
26738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
26748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			{
26758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		wx		= (float)px + 0.5f;
26768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		wy		= (float)py + 0.5f;
26778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		nx		= wx / dstW;
26788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		ny		= wy / dstH;
26798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool		tri0	= nx + ny - posEps <= 1.0f;
26818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool		tri1	= nx + ny + posEps >= 1.0f;
26828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				bool			isOk	= false;
26848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				DE_ASSERT(tri0 || tri1);
26868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				// Pixel can belong to either of the triangles if it lies close enough to the edge.
26888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
26898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
26908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triWx		= triNdx ? dstW - wx : wx;
26918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triWy		= triNdx ? dstH - wy : wy;
26928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triNx		= triNdx ? 1.0f - nx : nx;
26938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triNy		= triNdx ? 1.0f - ny : ny;
26948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec4	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
26968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
26978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy),
26988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 projectedTriInterpolate(triQ[triNdx], triW[triNdx], triNx, triNy));
26998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
27008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
27018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
27028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
27038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
27048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
27058852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27068852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord.toWidth<3>(), coordDx, coordDy, srcSize, lodPrec);
27078852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					// Compute lod bounds across lodOffsets range.
27098852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
27108852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					{
27118852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		wxo			= triWx + lodOffsets[lodOffsNdx].x();
27128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		wyo			= triWy + lodOffsets[lodOffsNdx].y();
27138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		nxo			= wxo/dstW;
27148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		nyo			= wyo/dstH;
27158852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
27178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
27188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
27198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
27208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
27218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
27228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
27238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
27248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
27258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
27268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
27288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
27298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					}
27308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
27328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coordBits, coord, clampedLod, resPix))
27348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					{
27358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						isOk = true;
27368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						break;
27378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					}
27388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
27398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				if (!isOk)
27418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
27428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
27438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					numFailed += 1;
27448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
27458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			}
27468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
27478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
27488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return numFailed;
27508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
27518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
27538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
27548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::TextureCubeArrayView&		src,
27558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const float*							texCoord,
27568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const ReferenceParams&				sampleParams,
27578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
27588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::IVec4&						coordBits,
27598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
27608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
27618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
27628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
27638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
27648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
27658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	int				numFailedPixels;
27668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
27688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
27708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, coordBits, lodPrec, testCtx.getWatchDog());
27718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (numFailedPixels > 0)
27738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
27748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
27768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
27778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (numFailedPixels > 0)
27798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
27808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
27813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
27823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
27833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
27853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
27873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
27883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Shadow lookup verification
27903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
27913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
27923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::ConstPixelBufferAccess&	reference,
27933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::PixelBufferAccess&		errorMask,
27943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Texture2DView&			src,
27953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const float*							texCoord,
27963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const ReferenceParams&				sampleParams,
27973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TexComparePrecision&		comparePrec,
27983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::LodPrecision&				lodPrec,
27993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Vec3&						nonShadowThreshold)
28003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
28023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
28033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
28053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
28063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
28083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
28093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
28103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
28113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
28133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
28143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
28153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
28163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
28183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
28203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
28223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
28243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
28253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
28263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
28273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
28283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
28303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
28323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
28343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
28353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= result.getPixel(px, py);
28363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= reference.getPixel(px, py);
28373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Other channels should trivially match to reference.
28393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
28403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
28413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
28423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
28433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
28443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
28453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
28473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
28483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
28493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
28503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
28513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
28533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
28543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
28553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
28563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
28573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
28593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
28603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
28613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
28623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
28633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
28643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
28663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
28683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
28693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
28703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
28713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
28723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
28733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
28743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
28763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo));
28773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
28783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
28793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
28803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
28813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
28823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
28843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
28853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
28863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
28883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
28893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
28913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
28923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
28933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
28943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
28953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
28963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
28973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
29003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
29033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::ConstPixelBufferAccess&	reference,
29043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::PixelBufferAccess&		errorMask,
29053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TextureCubeView&			src,
29063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const float*							texCoord,
29073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const ReferenceParams&				sampleParams,
29083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TexComparePrecision&		comparePrec,
29093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::LodPrecision&				lodPrec,
29103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Vec3&						nonShadowThreshold)
29113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
29133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
29143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
29163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
29173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
29183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
29203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
29213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
29223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			srcSize			= src.getSize();
29233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
29253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
29263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
29273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
29283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
29293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
29313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
29333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
29353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
29373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
29383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
29393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
29403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
29413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
29433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
29453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
29473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
29483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= result.getPixel(px, py);
29493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= reference.getPixel(px, py);
29503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
29523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
29533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
29543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
29553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
29563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
29573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
29593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
29603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
29613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
29623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
29633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
29653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
29663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
29673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
29683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
29693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
29713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
29723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
29733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
29743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
29753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
29763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
29773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
29783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
29793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
29813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
29833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
29843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
29853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
29863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
29873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
29883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
29893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
29913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
29923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
29933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
29943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
29953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
29963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
29973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
29983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
29993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
30003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
30023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
30033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
30043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
30063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
30073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
30093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
30113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
30123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
30133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
30143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
30153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
30183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
30213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::ConstPixelBufferAccess&	reference,
30223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::PixelBufferAccess&		errorMask,
30233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Texture2DArrayView&		src,
30243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const float*							texCoord,
30253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const ReferenceParams&				sampleParams,
30263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TexComparePrecision&		comparePrec,
30273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::LodPrecision&				lodPrec,
30283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Vec3&						nonShadowThreshold)
30293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
30313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
30323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
30343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
30353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
30363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
30383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
30393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
30403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
30413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
30433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
30443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
30453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
30463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
30473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
30493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
30513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
30533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
30553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
30563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
30573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
30583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
30593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
30613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
30633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
30653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
30663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= result.getPixel(px, py);
30673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= reference.getPixel(px, py);
30683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
30703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
30713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
30723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
30733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
30743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
30753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
30773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
30783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
30793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
30803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
30813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
30833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
30843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
30853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
30863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
30873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
30893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
30903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
30913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
30923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
30933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
30943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
30953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
30973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
30993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
31003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
31013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
31023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
31033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
31043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
31053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
31073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo));
31083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
31093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
31103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
31113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
31123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
31133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
31153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
31163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
31173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
31193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
31203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
31223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
31233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
31243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
31253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
31263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
31273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
31283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
31313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Mipmap generation comparison.
31343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int compareGenMipmapBilinear (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
31363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
31383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstW		= float(dst.getWidth());
31403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstH		= float(dst.getHeight());
31413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcW		= float(src.getWidth());
31423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcH		= float(src.getHeight());
31433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailed	= 0;
31443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Translation to lookup verification parameters.
31463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
31473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */);
31483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::LookupPrecision	lookupPrec;
31493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorThreshold	= precision.colorThreshold;
31513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorMask		= precision.colorMask;
31523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.coordBits		= tcu::IVec3(22);
31533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.uvwBits			= precision.filterBits;
31543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
31563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < dst.getWidth(); x++)
31573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	result	= dst.getPixel(x, y);
31593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cx		= (float(x)+0.5f) / dstW * srcW;
31603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cy		= (float(y)+0.5f) / dstH * srcH;
31613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		isOk	= tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result);
31623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		errorMask.setPixel(isOk ? tcu::RGBA::green.toVec() : tcu::RGBA::red.toVec(), x, y);
31643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
31653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numFailed += 1;
31663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
31693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int compareGenMipmapBox (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
31723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
31743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstW		= float(dst.getWidth());
31763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstH		= float(dst.getHeight());
31773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcW		= float(src.getWidth());
31783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcH		= float(src.getHeight());
31793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailed	= 0;
31803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Translation to lookup verification parameters.
31823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
31833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */);
31843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::LookupPrecision	lookupPrec;
31853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorThreshold	= precision.colorThreshold;
31873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorMask		= precision.colorMask;
31883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.coordBits		= tcu::IVec3(22);
31893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.uvwBits			= precision.filterBits;
31903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
31923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < dst.getWidth(); x++)
31933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	result	= dst.getPixel(x, y);
31953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cx		= deFloatFloor(float(x) / dstW * srcW) + 1.0f;
31963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cy		= deFloatFloor(float(y) / dstH * srcH) + 1.0f;
31973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		isOk	= tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result);
31983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		errorMask.setPixel(isOk ? tcu::RGBA::green.toVec() : tcu::RGBA::red.toVec(), x, y);
32003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
32013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numFailed += 1;
32023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
32053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32073c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int compareGenMipmapVeryLenient (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
32083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
32103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(precision);
32113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstW		= float(dst.getWidth());
32133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstH		= float(dst.getHeight());
32143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcW		= float(src.getWidth());
32153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcH		= float(src.getHeight());
32163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailed	= 0;
32173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
32193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < dst.getWidth(); x++)
32203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	result	= dst.getPixel(x, y);
32223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		minX		= deFloorFloatToInt32(float(x-0.5f) / dstW * srcW);
32233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		minY		= deFloorFloatToInt32(float(y-0.5f) / dstH * srcH);
32243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		maxX		= deCeilFloatToInt32(float(x+1.5f) / dstW * srcW);
32253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		maxY		= deCeilFloatToInt32(float(y+1.5f) / dstH * srcH);
32263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec4		minVal, maxVal;
32273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool			isOk;
32283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(minX < maxX && minY < maxY);
32303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ky = minY; ky <= maxY; ky++)
32323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int kx = minX; kx <= maxX; kx++)
32343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
32353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		sx		= de::clamp(kx, 0, src.getWidth()-1);
32363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		sy		= de::clamp(ky, 0, src.getHeight()-1);
32373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec4	sample	= src.getPixel(sx, sy);
32383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ky == minY && kx == minX)
32403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
32413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					minVal = sample;
32423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					maxVal = sample;
32433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
32443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
32453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
32463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					minVal = min(sample, minVal);
32473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					maxVal = max(sample, maxVal);
32483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
32493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
32503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		isOk = boolAll(logicalAnd(lessThanEqual(minVal, result), lessThanEqual(result, maxVal)));
32533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		errorMask.setPixel(isOk ? tcu::RGBA::green.toVec() : tcu::RGBA::red.toVec(), x, y);
32553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
32563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numFailed += 1;
32573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
32603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::Texture2D& resultTexture, const tcu::Texture2D& level0Reference, const GenMipmapPrecision& precision)
32633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpTestResult result = QP_TEST_RESULT_PASS;
32653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Special comparison for level 0.
32673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		threshold	= select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask);
32693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			level0Ok	= tcu::floatThresholdCompare(log, "Level0", "Level 0", level0Reference.getLevel(0), resultTexture.getLevel(0), threshold, tcu::COMPARE_LOG_RESULT);
32703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!level0Ok)
32723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "ERROR: Level 0 comparison failed!" << TestLog::EndMessage;
32743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_FAIL;
32753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++)
32793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ConstPixelBufferAccess	src			= resultTexture.getLevel(levelNdx-1);
32813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ConstPixelBufferAccess	dst			= resultTexture.getLevel(levelNdx);
32823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Surface						errorMask	(dst.getWidth(), dst.getHeight());
32833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool								levelOk		= false;
32843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Try different comparisons in quality order.
32863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
32883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision);
32903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numFailed == 0)
32913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelOk = true;
32923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
32933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "WARNING: Level " << levelNdx << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
32943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
32973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision);
32993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numFailed == 0)
33003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelOk = true;
33013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
33023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "WARNING: Level " << levelNdx << " comparison to box method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
33033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// At this point all high-quality methods have been used.
33063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk && result == QP_TEST_RESULT_PASS)
33073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_QUALITY_WARNING;
33083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision);
33123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numFailed == 0)
33133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelOk = true;
33143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
33153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "ERROR: Level " << levelNdx << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << TestLog::EndMessage;
33163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_FAIL;
33203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::ImageSet(string("Level") + de::toString(levelNdx), string("Level ") + de::toString(levelNdx) + " result")
33223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("Result", "Result", dst);
33233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Image("ErrorMask", "Error mask", errorMask);
33263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::EndImageSet;
33283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
33313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
33323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::TextureCube& resultTexture, const tcu::TextureCube& level0Reference, const GenMipmapPrecision& precision)
33343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
33353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpTestResult result = QP_TEST_RESULT_PASS;
33363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_faceNames[] = { "-X", "+X", "-Y", "+Y", "-Z", "+Z" };
33383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_faceNames) == tcu::CUBEFACE_LAST);
33393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Special comparison for level 0.
33413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
33423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::CubeFace	face		= tcu::CubeFace(faceNdx);
33443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		threshold	= select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask);
33453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			level0Ok	= tcu::floatThresholdCompare(log,
33463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 ("Level0Face" + de::toString(faceNdx)).c_str(),
33473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 (string("Level 0, face ") + s_faceNames[face]).c_str(),
33483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 level0Reference.getLevelFace(0, face),
33493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 resultTexture.getLevelFace(0, face),
33503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 threshold, tcu::COMPARE_LOG_RESULT);
33513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!level0Ok)
33533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "ERROR: Level 0, face " << s_faceNames[face] << " comparison failed!" << TestLog::EndMessage;
33553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_FAIL;
33563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++)
33603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
33623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::CubeFace					face		= tcu::CubeFace(faceNdx);
33643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*							faceName	= s_faceNames[face];
33653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::ConstPixelBufferAccess	src			= resultTexture.getLevelFace(levelNdx-1,	face);
33663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::ConstPixelBufferAccess	dst			= resultTexture.getLevelFace(levelNdx,		face);
33673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Surface						errorMask	(dst.getWidth(), dst.getHeight());
33683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool								levelOk		= false;
33693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try different comparisons in quality order.
33713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
33733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
33743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision);
33753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numFailed == 0)
33763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levelOk = true;
33773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
33783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
33793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
33803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
33823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
33833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision);
33843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numFailed == 0)
33853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levelOk = true;
33863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
33873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName <<" comparison to box method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
33883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
33893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// At this point all high-quality methods have been used.
33913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk && result == QP_TEST_RESULT_PASS)
33923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result = QP_TEST_RESULT_QUALITY_WARNING;
33933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
33953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
33963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision);
33973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numFailed == 0)
33983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levelOk = true;
33993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
34003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "ERROR: Level " << levelNdx << ", face " << faceName << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << TestLog::EndMessage;
34013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
34023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
34043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result = QP_TEST_RESULT_FAIL;
34053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::ImageSet(string("Level") + de::toString(levelNdx) + "Face" + de::toString(faceNdx), string("Level ") + de::toString(levelNdx) + ", face " + string(faceName) + " result")
34073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< TestLog::Image("Result", "Result", dst);
34083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
34103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Image("ErrorMask", "Error mask", errorMask);
34113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::EndImageSet;
34133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
34143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
34173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
34183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Logging utilities.
34203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const LogGradientFmt& fmt)
34223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << "(R: " << fmt.valueMin->x() << " -> " << fmt.valueMax->x() << ", "
34243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   <<  "G: " << fmt.valueMin->y() << " -> " << fmt.valueMax->y() << ", "
34253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   <<  "B: " << fmt.valueMin->z() << " -> " << fmt.valueMax->z() << ", "
34263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   <<  "A: " << fmt.valueMin->w() << " -> " << fmt.valueMax->w() << ")";
34273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
34283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // TextureTestUtil
34303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gls
34313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
3432