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