13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL (ES) Module
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -----------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Texture test utilities.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glsTextureTestUtil.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDefs.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTestLog.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuVectorUtil.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuImageCompare.hpp"
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuStringTemplate.hpp"
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTexLookupVerifier.hpp"
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTexCompareVerifier.hpp"
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "qpWatchDog.h"
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing tcu::TestLog;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::map;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace deqp
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gls
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace TextureTestUtil
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulosenum
54b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos{
55b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos	MIN_SUBPIXEL_BITS	= 4
56b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos};
57b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
583c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySamplerType getSamplerType (tcu::TextureFormat format)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::TextureFormat;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (format.type)
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT8:
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT16:
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT32:
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_INT;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT8:
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT32:
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_1010102_REV:
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_UINT;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Texture formats used in depth/stencil textures.
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT16:
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_24_8:
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FLOAT : SAMPLERTYPE_UINT;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FLOAT;
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySamplerType getFetchSamplerType (tcu::TextureFormat format)
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using tcu::TextureFormat;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (format.type)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT8:
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT16:
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::SIGNED_INT32:
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FETCH_INT;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT8:
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT32:
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_1010102_REV:
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FETCH_UINT;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Texture formats used in depth/stencil textures.
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT16:
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case TextureFormat::UNSIGNED_INT_24_8:
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FETCH_FLOAT : SAMPLERTYPE_FETCH_UINT;
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return SAMPLERTYPE_FETCH_FLOAT;
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Texture1DView getSubView (const tcu::Texture1DView& view, int baseLevel, int maxLevel)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Texture1DView(numLevels, view.getLevels()+clampedBase);
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Texture2DView getSubView (const tcu::Texture2DView& view, int baseLevel, int maxLevel)
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Texture2DView(numLevels, view.getLevels()+clampedBase);
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::TextureCubeView getSubView (const tcu::TextureCubeView& view, int baseLevel, int maxLevel)
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int							clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int							clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int							numLevels	= clampedMax-clampedBase+1;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::ConstPixelBufferAccess*	levels[tcu::CUBEFACE_LAST];
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		levels[face] = view.getFaceLevels((tcu::CubeFace)face) + clampedBase;
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::TextureCubeView(numLevels, levels);
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic tcu::Texture3DView getSubView (const tcu::Texture3DView& view, int baseLevel, int maxLevel)
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::Texture3DView(numLevels, view.getLevels()+clampedBase);
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrystatic tcu::TextureCubeArrayView getSubView (const tcu::TextureCubeArrayView& view, int baseLevel, int maxLevel)
1488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
1498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
1508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
1518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const int	numLevels	= clampedMax-clampedBase+1;
1528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return tcu::TextureCubeArrayView(numLevels, view.getLevels()+clampedBase);
1538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
1548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float linearInterpolate (float t, float minVal, float maxVal)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return minVal + (maxVal - minVal) * t;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::Vec4 linearInterpolate (float t, const tcu::Vec4& a, const tcu::Vec4& b)
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return a + (b - a) * t;
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float bilinearInterpolate (float x, float y, const tcu::Vec4& quad)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w00 = (1.0f-x)*(1.0f-y);
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w01 = (1.0f-x)*y;
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w10 = x*(1.0f-y);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float w11 = x*y;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return quad.x()*w00 + quad.y()*w10 + quad.z()*w01 + quad.w()*w11;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float triangleInterpolate (float v0, float v1, float v2, float x, float y)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return v0 + (v2-v0)*x + (v1-v0)*y;
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float triangleInterpolate (const tcu::Vec3& v, float x, float y)
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return triangleInterpolate(v.x(), v.y(), v.z(), x, y);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySurfaceAccess::SurfaceAccess (tcu::Surface& surface, const tcu::PixelFormat& colorFmt, int x, int y, int width, int height)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_surface		(&surface)
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colorMask	(getColorMask(colorFmt))
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_x			(x)
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_y			(y)
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width		(width)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height		(height)
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1943c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySurfaceAccess::SurfaceAccess (tcu::Surface& surface, const tcu::PixelFormat& colorFmt)
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_surface		(&surface)
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colorMask	(getColorMask(colorFmt))
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_x			(0)
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_y			(0)
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width		(surface.getWidth())
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height		(surface.getHeight())
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySurfaceAccess::SurfaceAccess (const SurfaceAccess& parent, int x, int y, int width, int height)
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_surface			(parent.m_surface)
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_colorMask		(parent.m_colorMask)
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_x				(parent.m_x + x)
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_y				(parent.m_y + y)
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width			(width)
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height			(height)
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 1D lookup LOD computation.
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float computeLodFromDerivates (LodMode mode, float dudx, float dudy)
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float p = 0.0f;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note [mika] Min and max bounds equal to exact with 1D textures
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_EXACT:
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MIN_BOUND:
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MAX_BOUND:
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(p);
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, deInt32 srcSize, const tcu::Vec3& sq)
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dux	= (sq.z() - sq.x()) * (float)srcSize;
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float duy	= (sq.y() - sq.x()) * (float)srcSize;
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dx	= (float)dstSize.x();
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dy	= (float)dstSize.y();
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dux/dx, duy/dy);
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 2D lookup LOD computation.
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dudy, float dvdy)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float p = 0.0f;
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_EXACT:
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx), deFloatSqrt(dudy*dudy + dvdy*dvdy));
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MIN_BOUND:
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MAX_BOUND:
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = mode == LODMODE_MIN_BOUND ? de::max(mu, mv) : mu + mv;
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(p);
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, const tcu::IVec2& srcSize, const tcu::Vec3& sq, const tcu::Vec3& tq)
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dux	= (sq.z() - sq.x()) * (float)srcSize.x();
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float duy	= (sq.y() - sq.x()) * (float)srcSize.x();
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvx	= (tq.z() - tq.x()) * (float)srcSize.y();
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvy	= (tq.y() - tq.x()) * (float)srcSize.y();
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dx	= (float)dstSize.x();
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dy	= (float)dstSize.y();
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dux/dx, dvx/dx, duy/dy, dvy/dy);
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 3D lookup LOD computation.
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dwdx, float dudy, float dvdy, float dwdy)
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float p = 0.0f;
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (mode)
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_EXACT:
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx + dwdx*dwdx), deFloatSqrt(dudy*dudy + dvdy*dvdy + dwdy*dwdy));
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MIN_BOUND:
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case LODMODE_MAX_BOUND:
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float mw = de::max(deFloatAbs(dwdx), deFloatAbs(dwdy));
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			p = mode == LODMODE_MIN_BOUND ? de::max(de::max(mu, mv), mw) : (mu + mv + mw);
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deFloatLog2(p);
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3143c827367444ee418f129b2c238299f49d3264554Jarkko 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)
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dux	= (sq.z() - sq.x()) * (float)srcSize.x();
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float duy	= (sq.y() - sq.x()) * (float)srcSize.x();
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvx	= (tq.z() - tq.x()) * (float)srcSize.y();
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvy	= (tq.y() - tq.x()) * (float)srcSize.y();
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwx	= (rq.z() - rq.x()) * (float)srcSize.z();
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwy	= (rq.y() - rq.x()) * (float)srcSize.z();
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dx	= (float)dstSize.x();
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dy	= (float)dstSize.y();
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dux/dx, dvx/dx, dwx/dx, duy/dy, dvy/dy, dwy/dy);
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny)
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3303c827367444ee418f129b2c238299f49d3264554Jarkko 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]);
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float triDerivateX (const tcu::Vec3& s, const tcu::Vec3& w, float wx, float width, float ny)
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float d = w[1]*w[2]*(width*(ny - 1.0f) + wx) - w[0]*(w[2]*width*ny + w[1]*wx);
3363c827367444ee418f129b2c238299f49d3264554Jarkko 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);
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float triDerivateY (const tcu::Vec3& s, const tcu::Vec3& w, float wy, float height, float nx)
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float d = w[1]*w[2]*(height*(nx - 1.0f) + wy) - w[0]*(w[1]*height*nx + w[2]*wy);
3423c827367444ee418f129b2c238299f49d3264554Jarkko 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);
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 1D lookup LOD.
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& projection, float wx, float wy, float width, float height)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Exact derivatives.
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dudx, dudy);
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 2D lookup LOD.
3563c827367444ee418f129b2c238299f49d3264554Jarkko 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)
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Exact derivatives.
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdx	= triDerivateX(v, projection, wx, width, wy/height);
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdy	= triDerivateY(v, projection, wy, height, wx/width);
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dudx, dvdx, dudy, dvdy);
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 3D lookup LOD.
3683c827367444ee418f129b2c238299f49d3264554Jarkko 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)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Exact derivatives.
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdx	= triDerivateX(v, projection, wx, width, wy/height);
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdx	= triDerivateX(w, projection, wx, width, wy/height);
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dvdy	= triDerivateY(v, projection, wy, height, wx/width);
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float dwdy	= triDerivateY(w, projection, wy, height, wx/width);
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return computeLodFromDerivates(mode, dudx, dvdx, dwdx, dudy, dvdy, dwdy);
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture1DView& src, const ReferenceParams& params, float s, float lod)
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, lod), 0.0, 0.0, 1.0f);
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, lod);
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture2DView& src, const ReferenceParams& params, float s, float t, float lod)
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f);
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, lod);
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::TextureCubeView& src, const ReferenceParams& params, float s, float t, float r, float lod)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f);
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, r, lod);
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture2DArrayView& src, const ReferenceParams& params, float s, float t, float r, float lod)
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f);
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, r, lod);
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::TextureCubeArrayView& src, const ReferenceParams& params, float s, float t, float r, float q, float lod)
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, q, lod), 0.0, 0.0, 1.0f);
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, r, q, lod);
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline tcu::Vec4 execSample (const tcu::Texture1DArrayView& src, const ReferenceParams& params, float s, float t, float lod)
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f);
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return src.sample(params.sampler, s, t, lod);
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
42923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params)
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
43123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
43223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
4330d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture1DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
43423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
43523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
43723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
43823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											srcSize				= src.getWidth();
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
44123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
44223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias, params.minLod, params.maxLod),
44323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry																		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
46423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
46623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
46723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
4680d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture2DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
47023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
47123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
47223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
47323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec2									srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
47623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
47723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
47823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod),
47923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) };
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y);
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
50123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params)
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
50323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
50423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
5050d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture1DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
50623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
50723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
50823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										dstW				= (float)dst.getWidth();
50923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										dstH				= (float)dst.getHeight();
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec4									uq					= sq * (float)src.getWidth();
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
51423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
51523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wx		= (float)px + 0.5f;
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wy		= (float)py + 0.5f;
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	nx		= wx / dstW;
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	ny		= wy / dstH;
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWx	= triNdx ? dstW - wx : wx;
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWy	= triNdx ? dstH - wy : wy;
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNx	= triNdx ? 1.0f - nx : nx;
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNy	= triNdx ? 1.0f - ny : ny;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							+ lodBias;
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, lod) * params.colorScale + params.colorBias, px, py);
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
54323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
54423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
5450d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture2DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
54823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										dstW				= (float)dst.getWidth();
54923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										dstH				= (float)dst.getHeight();
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
55123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec4									uq					= sq * (float)src.getWidth();
55223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec4									vq					= tq * (float)src.getHeight();
55323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
55423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
55523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
55623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
55723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triV[2]				= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
55823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wx		= (float)px + 0.5f;
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wy		= (float)py + 0.5f;
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	nx		= wx / dstW;
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	ny		= wy / dstH;
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWx	= triNdx ? dstW - wx : wx;
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWy	= triNdx ? dstH - wy : wy;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNx	= triNdx ? 1.0f - nx : nx;
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNy	= triNdx ? 1.0f - ny : ny;
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy);
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							+ lodBias;
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, px, py);
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture2DView& src, const float* texCoord, const ReferenceParams& params)
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture2DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & ReferenceParams::PROJECTED)
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureProjected(dst, view, sq, tq, params);
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureNonProjected(dst, view, sq, tq, params);
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture1DView& src, const float* texCoord, const ReferenceParams& params)
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture1DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & ReferenceParams::PROJECTED)
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureProjected(dst, view, sq, params);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureNonProjected(dst, view, sq, params);
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic float computeCubeLodFromDerivates (LodMode lodMode, const tcu::Vec3& coord, const tcu::Vec3& coordDx, const tcu::Vec3& coordDy, const int faceSize)
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::CubeFace	face	= tcu::selectCubeFace(coord);
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					maNdx	= 0;
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					sNdx	= 0;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					tNdx	= 0;
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note Derivate signs don't matter when computing lod
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X:
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break;
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y:
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break;
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z:
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break;
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		sc		= coord[sNdx];
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		tc		= coord[tNdx];
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		ma		= de::abs(coord[maNdx]);
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		scdx	= coordDx[sNdx];
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		tcdx	= coordDx[tNdx];
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		madx	= de::abs(coordDx[maNdx]);
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		scdy	= coordDy[sNdx];
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		tcdy	= coordDy[tNdx];
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		mady	= de::abs(coordDy[maNdx]);
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dudx	= float(faceSize) * 0.5f * (scdx*ma - sc*madx) / (ma*ma);
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dvdx	= float(faceSize) * 0.5f * (tcdx*ma - tc*madx) / (ma*ma);
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dudy	= float(faceSize) * 0.5f * (scdy*ma - sc*mady) / (ma*ma);
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		dvdy	= float(faceSize) * 0.5f * (tcdy*ma - tc*mady) / (ma*ma);
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return computeLodFromDerivates(lodMode, dudx, dvdx, dudy, dvdy);
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
64723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureCube (const SurfaceAccess& dst, const tcu::TextureCubeView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
64923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
65023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
6510d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::TextureCubeView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
65223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
65323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
65423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
65523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
65623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const int									srcSize				= src.getSize();
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
65923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
66023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
66123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
66223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
66423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									lodBias				((params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f);
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wx		= (float)px + 0.5f;
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wy		= (float)py + 0.5f;
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		nx		= wx / dstW;
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		ny		= wy / dstH;
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNx	= triNdx ? 1.0f - nx : nx;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNy	= triNdx ? 1.0f - ny : ny;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coord		(triangleInterpolate(triS[triNdx], triNx, triNy),
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triangleInterpolate(triT[triNdx], triNx, triNy),
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triangleInterpolate(triR[triNdx], triNx, triNy));
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		lod			= de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, srcSize) + lodBias, params.minLod, params.maxLod);
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), lod) * params.colorScale + params.colorBias, px, py);
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeView& src, const float* texCoord, const ReferenceParams& params)
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::TextureCubeView	view	= getSubView(src, params.baseLevel, params.maxLevel);
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				rq		= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
70323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	return sampleTextureCube(dst, view, sq, tq, rq, params);
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
70623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
70823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
70923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
7100d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture2DArrayView				src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
71123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
71223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
71423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
71523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec2									srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
71823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
71923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
72023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
72123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										triLod[2]			= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias,
72223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry																		computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias};
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	r		= triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY);
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, r, lod) * params.colorScale + params.colorBias, x, y);
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture2DArrayView& src, const float* texCoord, const ReferenceParams& params)
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2012-02-17 pyry] Support projected lookups.
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTextureNonProjected(dst, src, sq, tq, rq, params);
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
75523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
75723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
75823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
7590d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture1DArrayView				src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
76123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
76223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
76323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
76423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	deInt32										srcSize				= src.getWidth();
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
76723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
76823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
76923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										triLod[2]			= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias,
77023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry																		computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias};
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y);
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture1DArrayView& src, const float* texCoord, const ReferenceParams& params)
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2014-06-09 mika] Support projected lookups.
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTextureNonProjected(dst, src, sq, tq, params);
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
80123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
80323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
80423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
8050d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture3DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
80623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
80723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
80923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
81023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::IVec3									srcSize				= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
81323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
81423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
81523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
81623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias, params.minLod, params.maxLod),
81723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias, params.minLod, params.maxLod) };
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triX	= triNdx ? 1.0f-xf : xf;
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triY	= triNdx ? 1.0f-yf : yf;
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	r		= triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY);
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= triLod[triNdx];
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, x, y);
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
84023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
84223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
84323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
8440d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture3DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
84523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
84623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
84723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										dstW				= (float)dst.getWidth();
84823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	float										dstH				= (float)dst.getHeight();
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
85023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec4									uq					= sq * (float)src.getWidth();
85123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec4									vq					= tq * (float)src.getHeight();
85223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec4									wq					= rq * (float)src.getDepth();
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
85423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
85523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
85623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
85723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
85823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triV[2]				= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
85923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triW[2]				= { wq.swizzle(0, 1, 2), wq.swizzle(3, 2, 1) };
86023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triP[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wx		= (float)px + 0.5f;
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	wy		= (float)py + 0.5f;
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	nx		= wx / dstW;
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	ny		= wy / dstH;
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWx	= triNdx ? dstW - wx : wx;
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triWy	= triNdx ? dstH - wy : wy;
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNx	= triNdx ? 1.0f - nx : nx;
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	triNy	= triNdx ? 1.0f - ny : ny;
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	s		= projectedTriInterpolate(triS[triNdx], triP[triNdx], triNx, triNy);
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	t		= projectedTriInterpolate(triT[triNdx], triP[triNdx], triNx, triNy);
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	r		= projectedTriInterpolate(triR[triNdx], triP[triNdx], triNx, triNy);
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triP[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							+ lodBias;
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, px, py);
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::Texture3DView& src, const float* texCoord, const ReferenceParams& params)
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Texture3DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4				rq		= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & ReferenceParams::PROJECTED)
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureProjected(dst, view, sq, tq, rq, params);
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampleTextureNonProjected(dst, view, sq, tq, rq, params);
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
90123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyrystatic void sampleTextureCubeArray (const SurfaceAccess& dst, const tcu::TextureCubeArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const tcu::Vec4& qq, const ReferenceParams& params)
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
90323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	// Separate combined DS formats
90423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
9050d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::TextureCubeArrayView				src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
90623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
90723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= (float)dst.getWidth();
90823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= (float)dst.getHeight();
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
91123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
91223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
91323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
91423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	tcu::Vec3									triQ[2]				= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
91523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
91723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < dst.getHeight(); py++)
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < dst.getWidth(); px++)
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wx		= (float)px + 0.5f;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		wy		= (float)py + 0.5f;
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		nx		= wx / dstW;
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		ny		= wy / dstH;
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNx	= triNdx ? 1.0f - nx : nx;
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		triNy	= triNdx ? 1.0f - ny : ny;
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coord	(triangleInterpolate(triS[triNdx], triNx, triNy),
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triangleInterpolate(triT[triNdx], triNx, triNy),
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triangleInterpolate(triR[triNdx], triNx, triNy));
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float		coordQ	= triangleInterpolate(triQ[triNdx], triNx, triNy);
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDx	(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec3	coordDy	(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const float		lod		= de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, src.getSize()) + lodBias, params.minLod, params.maxLod);
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), coordQ, lod) * params.colorScale + params.colorBias, px, py);
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeArrayView& src, const float* texCoord, const ReferenceParams& params)
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4 qq = tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
95923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	sampleTextureCubeArray(dst, src, sq, tq, rq, qq, params);
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid fetchTexture (const SurfaceAccess& dst, const tcu::ConstPixelBufferAccess& src, const float* texCoord, const tcu::Vec4& colorScale, const tcu::Vec4& colorBias)
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq			= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int	triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	triX	= triNdx ? 1.0f-xf : xf;
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	triY	= triNdx ? 1.0f-yf : yf;
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(src.getPixel((int)s, 0) * colorScale + colorBias, x, y);
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid clear (const SurfaceAccess& dst, const tcu::Vec4& color)
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int x = 0; x < dst.getWidth(); x++)
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dst.setPixel(color, x, y);
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareImages (TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold)
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::pixelThresholdCompare(log, "Result", "Image comparison result", reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool compareImages (TestLog& log, const char* name, const char* desc, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold)
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::pixelThresholdCompare(log, name, desc, reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint measureAccuracy (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, int bestScoreDiff, int worstScoreDiff)
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::measurePixelDiffAccuracy(log, "Result", "Image comparison result", reference, rendered, bestScoreDiff, worstScoreDiff, tcu::COMPARE_LOG_EVERYTHING);
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline int rangeDiff (int x, int a, int b)
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (x < a)
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return a-x;
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (x > b)
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return x-b;
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline tcu::RGBA rangeDiff (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b)
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int rMin = de::min(a.getRed(),		b.getRed());
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int rMax = de::max(a.getRed(),		b.getRed());
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int gMin = de::min(a.getGreen(),	b.getGreen());
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int gMax = de::max(a.getGreen(),	b.getGreen());
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int bMin = de::min(a.getBlue(),		b.getBlue());
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int bMax = de::max(a.getBlue(),		b.getBlue());
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int aMin = de::min(a.getAlpha(),	b.getAlpha());
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int aMax = de::max(a.getAlpha(),	b.getAlpha());
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tcu::RGBA(rangeDiff(p.getRed(),		rMin, rMax),
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 rangeDiff(p.getGreen(),	gMin, gMax),
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 rangeDiff(p.getBlue(),		bMin, bMax),
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 rangeDiff(p.getAlpha(),	aMin, aMax));
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool rangeCompare (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b, tcu::RGBA threshold)
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::RGBA diff = rangeDiff(p, a, b);
10373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return diff.getRed()	<= threshold.getRed() &&
10383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   diff.getGreen()	<= threshold.getGreen() &&
10393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   diff.getBlue()	<= threshold.getBlue() &&
10403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   diff.getAlpha()	<= threshold.getAlpha();
10413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10433c827367444ee418f129b2c238299f49d3264554Jarkko PoyryRandomViewport::RandomViewport (const tcu::RenderTarget& renderTarget, int preferredWidth, int preferredHeight, deUint32 seed)
10443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: x			(0)
10453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, y			(0)
10463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, width		(deMin32(preferredWidth, renderTarget.getWidth()))
10473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, height	(deMin32(preferredHeight, renderTarget.getHeight()))
10483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random rnd(seed);
10503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	x = rnd.getInt(0, renderTarget.getWidth()	- width);
10513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	y = rnd.getInt(0, renderTarget.getHeight()	- height);
10523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1054469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko PöyryProgramLibrary::ProgramLibrary (const glu::RenderContext& context, tcu::TestLog& log, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision)
10553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_context				(context)
1056469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry	, m_log					(log)
10573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_glslVersion			(glslVersion)
10583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_texCoordPrecision	(texCoordPrecision)
10593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10623c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgramLibrary::~ProgramLibrary (void)
10633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	clear();
10653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10673c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ProgramLibrary::clear (void)
10683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (map<Program, glu::ShaderProgram*>::iterator i = m_programs.begin(); i != m_programs.end(); i++)
10703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
10713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete i->second;
10723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		i->second = DE_NULL;
10733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_programs.clear();
10753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryglu::ShaderProgram* ProgramLibrary::getProgram (Program program)
10783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_programs.find(program) != m_programs.end())
10803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_programs[program]; // Return from cache.
10813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* vertShaderTemplate =
10833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_HEADER}"
10843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_IN} highp vec4 a_position;\n"
10853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_IN} ${PRECISION} ${TEXCOORD_TYPE} a_texCoord;\n"
10863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${VTX_OUT} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n"
10873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
10883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main (void)\n"
10893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
10903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	gl_Position = a_position;\n"
10913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	v_texCoord = a_texCoord;\n"
10923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
10933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* fragShaderTemplate =
10943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${FRAG_HEADER}"
10953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"${FRAG_IN} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n"
10963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} float u_bias;\n"
10973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} float u_ref;\n"
10983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} vec4 u_colorScale;\n"
10993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} vec4 u_colorBias;\n"
11003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"uniform ${PRECISION} ${SAMPLER_TYPE} u_sampler;\n"
11013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"\n"
11023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"void main (void)\n"
11033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"{\n"
11043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"	${FRAG_COLOR} = ${LOOKUP} * u_colorScale + u_colorBias;\n"
11053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		"}\n";
11063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	map<string, string> params;
11083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	isCube		= de::inRange<int>(program, PROGRAM_CUBE_FLOAT, PROGRAM_CUBE_SHADOW_BIAS);
11103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	isArray		= de::inRange<int>(program, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_2D_ARRAY_SHADOW)
11113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_1D_ARRAY_FLOAT, PROGRAM_1D_ARRAY_SHADOW);
11123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	is1D		= de::inRange<int>(program, PROGRAM_1D_FLOAT, PROGRAM_1D_UINT_BIAS)
11143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_1D_ARRAY_FLOAT, PROGRAM_1D_ARRAY_SHADOW)
11153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_BUFFER_FLOAT, PROGRAM_BUFFER_UINT);
11163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	is2D		= de::inRange<int>(program, PROGRAM_2D_FLOAT, PROGRAM_2D_UINT_BIAS)
11183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							|| de::inRange<int>(program, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_2D_ARRAY_SHADOW);
11193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	is3D		= de::inRange<int>(program, PROGRAM_3D_FLOAT, PROGRAM_3D_UINT_BIAS);
11213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool	isCubeArray	= de::inRange<int>(program, PROGRAM_CUBE_ARRAY_FLOAT, PROGRAM_CUBE_ARRAY_SHADOW);
11228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	bool	isBuffer	= de::inRange<int>(program, PROGRAM_BUFFER_FLOAT, PROGRAM_BUFFER_UINT);
11233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_glslVersion == glu::GLSL_VERSION_100_ES)
11253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_HEADER"]	= "";
11273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_HEADER"]	= "";
11283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_IN"]		= "attribute";
11293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_OUT"]		= "varying";
11303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_IN"]		= "varying";
11313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_COLOR"]	= "gl_FragColor";
11323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_glslVersion == glu::GLSL_VERSION_300_ES || m_glslVersion == glu::GLSL_VERSION_310_ES || m_glslVersion == glu::GLSL_VERSION_330)
11343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const string	version	= glu::getGLSLVersionDeclaration(m_glslVersion);
11368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		const char*		ext		= DE_NULL;
11378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
11388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (isCubeArray && glu::glslVersionIsES(m_glslVersion))
11398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			ext = "GL_EXT_texture_cube_map_array";
11408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		else if (isBuffer && glu::glslVersionIsES(m_glslVersion))
11418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			ext = "GL_EXT_texture_buffer";
11423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		params["FRAG_HEADER"]	= version + (ext ? string("\n#extension ") + ext + " : require" : string()) + "\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
11448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		params["VTX_HEADER"]	= version + "\n";
11453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_IN"]		= "in";
11463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["VTX_OUT"]		= "out";
11473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_IN"]		= "in";
11483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["FRAG_COLOR"]	= "dEQP_FragColor";
11493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
11503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!"Unsupported version");
11523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params["PRECISION"]		= glu::getPrecisionName(m_texCoordPrecision);
11543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isCubeArray)
11563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "vec4";
11573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isCube || (is2D && isArray) || is3D)
11583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "vec3";
11593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if ((is1D && isArray) || is2D)
11603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "vec2";
11613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (is1D)
11623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params["TEXCOORD_TYPE"]	= "float";
11633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
11643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
11653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*	sampler	= DE_NULL;
11673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*	lookup	= DE_NULL;
11683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
11693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_glslVersion == glu::GLSL_VERSION_300_ES || m_glslVersion == glu::GLSL_VERSION_310_ES || m_glslVersion == glu::GLSL_VERSION_330)
11703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
11713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (program)
11723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
11733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT:			sampler = "sampler2D";				lookup = "texture(u_sampler, v_texCoord)";												break;
11743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_INT:			sampler = "isampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_UINT:			sampler = "usampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_SHADOW:			sampler = "sampler2DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT_BIAS:		sampler = "sampler2D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
11783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_INT_BIAS:		sampler = "isampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_UINT_BIAS:		sampler = "usampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11803c827367444ee418f129b2c238299f49d3264554Jarkko 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;
11813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_FLOAT:			sampler = "sampler1D";				lookup = "texture(u_sampler, v_texCoord)";												break;
11823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_INT:			sampler = "isampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_UINT:			sampler = "usampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_SHADOW:			sampler = "sampler1DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_FLOAT_BIAS:		sampler = "sampler1D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
11863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_INT_BIAS:		sampler = "isampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_UINT_BIAS:		sampler = "usampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11883c827367444ee418f129b2c238299f49d3264554Jarkko 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;
11893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT:		sampler = "samplerCube";			lookup = "texture(u_sampler, v_texCoord)";												break;
11903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_INT:			sampler = "isamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_UINT:			sampler = "usamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_SHADOW:		sampler = "samplerCubeShadow";		lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
11933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT_BIAS:	sampler = "samplerCube";			lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
11943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_INT_BIAS:		sampler = "isamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_UINT_BIAS:	sampler = "usamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
11963c827367444ee418f129b2c238299f49d3264554Jarkko 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;
11973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_ARRAY_FLOAT:	sampler = "sampler2DArray";			lookup = "texture(u_sampler, v_texCoord)";												break;
11983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_ARRAY_INT:		sampler = "isampler2DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
11993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_ARRAY_UINT:		sampler = "usampler2DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
12003c827367444ee418f129b2c238299f49d3264554Jarkko 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;
12013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_FLOAT:			sampler = "sampler3D";				lookup = "texture(u_sampler, v_texCoord)";												break;
12023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_INT:			sampler = "isampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
1203465468f10563971a95c742ac9834e60de661524aJarkko Pöyry			case PROGRAM_3D_UINT:			sampler = "usampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
12043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_FLOAT_BIAS:		sampler = "sampler3D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
12053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_3D_INT_BIAS:		sampler = "isampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
1206465468f10563971a95c742ac9834e60de661524aJarkko Pöyry			case PROGRAM_3D_UINT_BIAS:		sampler = "usampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
12073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_ARRAY_FLOAT:	sampler = "samplerCubeArray";		lookup = "texture(u_sampler, v_texCoord)";												break;
12083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_ARRAY_INT:	sampler = "isamplerCubeArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
12093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_ARRAY_UINT:	sampler = "usamplerCubeArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
12103c827367444ee418f129b2c238299f49d3264554Jarkko 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;
12113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_ARRAY_FLOAT:	sampler = "sampler1DArray";			lookup = "texture(u_sampler, v_texCoord)";												break;
12123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_ARRAY_INT:		sampler = "isampler1DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
12133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_1D_ARRAY_UINT:		sampler = "usampler1DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
12143c827367444ee418f129b2c238299f49d3264554Jarkko 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;
12153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_BUFFER_FLOAT:		sampler = "samplerBuffer";			lookup = "texelFetch(u_sampler, int(v_texCoord))";										break;
12163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_BUFFER_INT:		sampler = "isamplerBuffer";			lookup = "vec4(texelFetch(u_sampler, int(v_texCoord)))";								break;
12173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_BUFFER_UINT:		sampler = "usamplerBuffer";			lookup = "vec4(texelFetch(u_sampler, int(v_texCoord)))";								break;
12183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
12193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
12203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_glslVersion == glu::GLSL_VERSION_100_ES)
12233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sampler = isCube ? "samplerCube" : "sampler2D";
12253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (program)
12273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
12283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT:			lookup = "texture2D(u_sampler, v_texCoord)";			break;
12293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_2D_FLOAT_BIAS:		lookup = "texture2D(u_sampler, v_texCoord, u_bias)";	break;
12303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT:		lookup = "textureCube(u_sampler, v_texCoord)";			break;
12313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case PROGRAM_CUBE_FLOAT_BIAS:	lookup = "textureCube(u_sampler, v_texCoord, u_bias)";	break;
12323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
12333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
12343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
12353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
12373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!"Unsupported version");
12383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params["SAMPLER_TYPE"]	= sampler;
12403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params["LOOKUP"]		= lookup;
12413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string vertSrc = tcu::StringTemplate(vertShaderTemplate).specialize(params);
12433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string fragSrc = tcu::StringTemplate(fragShaderTemplate).specialize(params);
12443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram* progObj = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(vertSrc, fragSrc));
12463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!progObj->isOk())
12473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1248469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry		m_log << *progObj;
12493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete progObj;
12503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Failed to compile shader program");
12513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
12543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_programs[program] = progObj;
12563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (...)
12583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		delete progObj;
12603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw;
12613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
12623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return progObj;
12643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1266469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko PöyryTextureRenderer::TextureRenderer (const glu::RenderContext& context, tcu::TestLog& log, glu::GLSLVersion glslVersion, glu::Precision texCoordPrecision)
12673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_renderCtx		(context)
1268469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry	, m_log				(log)
1269469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry	, m_programLibrary	(context, log, glslVersion, texCoordPrecision)
12703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12733c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureRenderer::~TextureRenderer (void)
12743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	clear();
12763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureRenderer::clear (void)
12793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_programLibrary.clear();
12813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureRenderer::renderQuad (int texUnit, const float* texCoord, TextureType texType)
12843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	renderQuad(texUnit, texCoord, RenderParams(texType));
12863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
12873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TextureRenderer::renderQuad (int texUnit, const float* texCoord, const RenderParams& params)
12893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
12903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl			= m_renderCtx.getFunctions();
12913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec4				wCoord		= params.flags & RenderParams::PROJECTED ? params.w : tcu::Vec4(1.0f);
12923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					useBias		= !!(params.flags & RenderParams::USE_BIAS);
12933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	bool					logUniforms	= !!(params.flags & RenderParams::LOG_UNIFORMS);
12943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
12953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Render quad with texture.
12963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float position[] =
12973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
12983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f*wCoord.x(), -1.0f*wCoord.x(), 0.0f, wCoord.x(),
12993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f*wCoord.y(), +1.0f*wCoord.y(), 0.0f, wCoord.y(),
13003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f*wCoord.z(), -1.0f*wCoord.z(), 0.0f, wCoord.z(),
13013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f*wCoord.w(), +1.0f*wCoord.w(), 0.0f, wCoord.w()
13023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
13033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const deUint16 indices[] = { 0, 1, 2, 2, 1, 3 };
13043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Program progSpec	= PROGRAM_LAST;
13063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		numComps	= 0;
13073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.texType == TEXTURETYPE_2D)
13083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 2;
13103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_2D_FLOAT_BIAS	: PROGRAM_2D_FLOAT;		break;
13143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_2D_INT_BIAS	: PROGRAM_2D_INT;		break;
13153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_2D_UINT_BIAS	: PROGRAM_2D_UINT;		break;
13163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_2D_SHADOW_BIAS	: PROGRAM_2D_SHADOW;	break;
13173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_1D)
13213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 1;
13233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_1D_FLOAT_BIAS	: PROGRAM_1D_FLOAT;		break;
13273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_1D_INT_BIAS	: PROGRAM_1D_INT;		break;
13283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_1D_UINT_BIAS	: PROGRAM_1D_UINT;		break;
13293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_1D_SHADOW_BIAS	: PROGRAM_1D_SHADOW;	break;
13303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_CUBE)
13343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 3;
13363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_CUBE_FLOAT_BIAS	: PROGRAM_CUBE_FLOAT;	break;
13403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_CUBE_INT_BIAS		: PROGRAM_CUBE_INT;		break;
13413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_CUBE_UINT_BIAS		: PROGRAM_CUBE_UINT;	break;
13423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_CUBE_SHADOW_BIAS	: PROGRAM_CUBE_SHADOW;	break;
13433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_3D)
13473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 3;
13493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_3D_FLOAT_BIAS	: PROGRAM_3D_FLOAT;		break;
13533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_3D_INT_BIAS	: PROGRAM_3D_INT;		break;
13543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_3D_UINT_BIAS	: PROGRAM_3D_UINT;		break;
13553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_2D_ARRAY)
13593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
13613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 3;
13633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_2D_ARRAY_FLOAT;	break;
13673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = PROGRAM_2D_ARRAY_INT;	break;
13683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_2D_ARRAY_UINT;	break;
13693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_2D_ARRAY_SHADOW;	break;
13703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_CUBE_ARRAY)
13743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!useBias);
13763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 4;
13783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_CUBE_ARRAY_FLOAT;	break;
13823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = PROGRAM_CUBE_ARRAY_INT;		break;
13833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_CUBE_ARRAY_UINT;		break;
13843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_CUBE_ARRAY_SHADOW;	break;
13853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
13863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
13873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
13883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_1D_ARRAY)
13893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
13903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
13913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 2;
13933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
13943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
13953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
13963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_1D_ARRAY_FLOAT;	break;
13973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_INT:		progSpec = PROGRAM_1D_ARRAY_INT;	break;
13983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_1D_ARRAY_UINT;	break;
13993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_1D_ARRAY_SHADOW;	break;
14003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:					DE_ASSERT(false);
14013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (params.texType == TEXTURETYPE_BUFFER)
14043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numComps = 1;
14063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (params.samplerType)
14083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FETCH_FLOAT:	progSpec = PROGRAM_BUFFER_FLOAT;	break;
14103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FETCH_INT:		progSpec = PROGRAM_BUFFER_INT;		break;
14113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case SAMPLERTYPE_FETCH_UINT:	progSpec = PROGRAM_BUFFER_UINT;		break;
14123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:						DE_ASSERT(false);
14133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
14143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
14163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
14173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	glu::ShaderProgram* program = m_programLibrary.getProgram(progSpec);
14193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2012-09-26 pyry] Move to ProgramLibrary and log unique programs only(?)
14213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.flags & RenderParams::LOG_PROGRAMS)
1422469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry		m_log << *program;
14233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Set vertex attributes");
14253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Program and uniforms.
14273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 prog = program->getProgram();
14283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.useProgram(prog);
14293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform1i(gl.getUniformLocation(prog, "u_sampler"), texUnit);
14313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (logUniforms)
1432469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry		m_log << TestLog::Message << "u_sampler = " << texUnit << TestLog::EndMessage;
14333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (useBias)
14353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(prog, "u_bias"), params.bias);
14373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (logUniforms)
1438469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry			m_log << TestLog::Message << "u_bias = " << params.bias << TestLog::EndMessage;
14393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (params.samplerType == SAMPLERTYPE_SHADOW)
14423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.uniform1f(gl.getUniformLocation(prog, "u_ref"), params.ref);
14443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (logUniforms)
1445469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry			m_log << TestLog::Message << "u_ref = " << params.ref << TestLog::EndMessage;
14463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform4fv(gl.getUniformLocation(prog, "u_colorScale"),	1, params.colorScale.getPtr());
14493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.uniform4fv(gl.getUniformLocation(prog, "u_colorBias"),	1, params.colorBias.getPtr());
14503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (logUniforms)
14523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1453469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry		m_log << TestLog::Message << "u_colorScale = " << params.colorScale << TestLog::EndMessage;
1454469002caa1ccd58f59f53a1bf3dbac4cf6a5d817Jarkko Pöyry		m_log << TestLog::Message << "u_colorBias = " << params.colorBias << TestLog::EndMessage;
14553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Set program state");
14583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
14603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const glu::VertexArrayBinding vertexArrays[] =
14613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
14623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("a_position",	4,			4, 0, &position[0]),
14633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			glu::va::Float("a_texCoord",	numComps,	4, 0, texCoord)
14643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
14653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		glu::draw(m_renderCtx, prog, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
14663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
14673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
14683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14703c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord1D (std::vector<float>& dst, float left, float right)
14713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4);
14733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = left;
14753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[1] = left;
14763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = right;
14773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = right;
14783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord1DArray (std::vector<float>& dst, int layerNdx, float left, float right)
14813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*2);
14833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = left;	dst[1] = (float)layerNdx;
14853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = left;	dst[3] = (float)layerNdx;
14863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[4] = right;	dst[5] = (float)layerNdx;
14873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = right;	dst[7] = (float)layerNdx;
14883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord2D (std::vector<float>& dst, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
14913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
14923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*2);
14933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
14943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = bottomLeft.x();	dst[1] = bottomLeft.y();
14953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[2] = bottomLeft.x();	dst[3] = topRight.y();
14963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[4] = topRight.x();		dst[5] = bottomLeft.y();
14973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = topRight.x();		dst[7] = topRight.y();
14983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
14993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord2DArray (std::vector<float>& dst, int layerNdx, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
15013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*3);
15033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = bottomLeft.x();	dst[ 1] = bottomLeft.y();	dst[ 2] = (float)layerNdx;
15053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = bottomLeft.x();	dst[ 4] = topRight.y();		dst[ 5] = (float)layerNdx;
15063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = topRight.x();		dst[ 7] = bottomLeft.y();	dst[ 8] = (float)layerNdx;
15073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9] = topRight.x();		dst[10] = topRight.y();		dst[11] = (float)layerNdx;
15083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoord3D (std::vector<float>& dst, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::IVec3& dirSwz)
15113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f0 = tcu::Vec3(0.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
15133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f1 = tcu::Vec3(0.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
15143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f2 = tcu::Vec3(1.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
15153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 f3 = tcu::Vec3(1.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
15163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v0 = p0 + (p1-p0)*f0;
15183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v1 = p0 + (p1-p0)*f1;
15193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v2 = p0 + (p1-p0)*f2;
15203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Vec3 v3 = p0 + (p1-p0)*f3;
15213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*3);
15233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0] = v0.x(); dst[ 1] = v0.y(); dst[ 2] = v0.z();
15253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3] = v1.x(); dst[ 4] = v1.y(); dst[ 5] = v1.z();
15263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6] = v2.x(); dst[ 7] = v2.y(); dst[ 8] = v2.z();
15273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9] = v3.x(); dst[10] = v3.y(); dst[11] = v3.z();
15283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face)
15313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordNegX[] =
15333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, -1.0f,
15353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, -1.0f,
15363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f,  1.0f,
15373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f,  1.0f
15383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordPosX[] =
15403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f,  1.0f,  1.0f,
15423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f, -1.0f,  1.0f,
15433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f,  1.0f, -1.0f,
15443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		+1.0f, -1.0f, -1.0f
15453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordNegY[] =
15473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f,  1.0f,
15493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, -1.0f,
15503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f,  1.0f,
15513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, -1.0f
15523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordPosY[] =
15543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, +1.0f, -1.0f,
15563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, +1.0f,  1.0f,
15573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, +1.0f, -1.0f,
15583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, +1.0f,  1.0f
15593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordNegZ[] =
15613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f,  1.0f, -1.0f,
15633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, -1.0f,
15643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, -1.0f,
15653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, -1.0f
15663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const float texCoordPosZ[] =
15683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f,  1.0f, +1.0f,
15703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		-1.0f, -1.0f, +1.0f,
15713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f,  1.0f, +1.0f,
15723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 1.0f, -1.0f, +1.0f
15733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
15743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float*	texCoord		= DE_NULL;
15763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				texCoordSize	= DE_LENGTH_OF_ARRAY(texCoordNegX);
15773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
15793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
15803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X: texCoord = texCoordNegX; break;
15813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: texCoord = texCoordPosX; break;
15823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y: texCoord = texCoordNegY; break;
15833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: texCoord = texCoordPosY; break;
15843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z: texCoord = texCoordNegZ; break;
15853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: texCoord = texCoordPosZ; break;
15863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
15873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
15883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
15893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
15903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(texCoordSize);
15923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::copy(texCoord, texCoord+texCoordSize, dst.begin());
15933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
15943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
15953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
15963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
15973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		sRow		= 0;
15983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		tRow		= 0;
15993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		mRow		= 0;
16003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	sSign		= 1.0f;
16013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	tSign		= 1.0f;
16023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	mSign		= 1.0f;
16033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
16053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;				   tSign = -1.0f;	break;
16073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;				sSign = -1.0f; tSign = -1.0f;	break;
16083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;				   tSign = -1.0f;	break;
16093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;												break;
16103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;	break;
16113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;							   tSign = -1.0f;	break;
16123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
16133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
16143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
16153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(3*4);
16183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0+mRow] = mSign;
16203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3+mRow] = mSign;
16213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6+mRow] = mSign;
16223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9+mRow] = mSign;
16233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0+sRow] = sSign * bottomLeft.x();
16253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3+sRow] = sSign * bottomLeft.x();
16263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6+sRow] = sSign * topRight.x();
16273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9+sRow] = sSign * topRight.x();
16283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[0+tRow] = tSign * bottomLeft.y();
16303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[3+tRow] = tSign * topRight.y();
16313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[6+tRow] = tSign * bottomLeft.y();
16323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[9+tRow] = tSign * topRight.y();
16333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryvoid computeQuadTexCoordCubeArray (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight, const tcu::Vec2& layerRange)
16363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
16373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			sRow	= 0;
16383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			tRow	= 0;
16393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			mRow	= 0;
16403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	qRow	= 3;
16413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		sSign	= 1.0f;
16423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		tSign	= 1.0f;
16433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float		mSign	= 1.0f;
16448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const float	l0		= layerRange.x();
16458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const float	l1		= layerRange.y();
16463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (face)
16483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
16493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;				   tSign = -1.0f;	break;
16503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;				sSign = -1.0f; tSign = -1.0f;	break;
16513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;				   tSign = -1.0f;	break;
16523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;												break;
16533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;	break;
16543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;							   tSign = -1.0f;	break;
16553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
16563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
16573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
16583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
16593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(4*4);
16613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 0+mRow] = mSign;
16633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 4+mRow] = mSign;
16643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 8+mRow] = mSign;
16653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[12+mRow] = mSign;
16663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 0+sRow] = sSign * bottomLeft.x();
16683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 4+sRow] = sSign * bottomLeft.x();
16693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 8+sRow] = sSign * topRight.x();
16703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[12+sRow] = sSign * topRight.x();
16713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 0+tRow] = tSign * bottomLeft.y();
16733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 4+tRow] = tSign * topRight.y();
16743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[ 8+tRow] = tSign * bottomLeft.y();
16753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst[12+tRow] = tSign * topRight.y();
16763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (l0 != l1)
16788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
16798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 0+qRow] = l0;
16808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 4+qRow] = l0*0.5f + l1*0.5f;
16818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 8+qRow] = l0*0.5f + l1*0.5f;
16828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[12+qRow] = l1;
16838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
16848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	else
16858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
16868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 0+qRow] = l0;
16878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 4+qRow] = l0;
16888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[ 8+qRow] = l0;
16898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		dst[12+qRow] = l0;
16908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
16913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
16923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Texture result verification
16943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
16953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
16963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
16973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
16983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
16993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture1DView&				baseView,
17003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
17013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
17023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
17033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
17043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
17053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
17063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
17073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
17083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
170923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
17100d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture1DView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
17113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
171223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
17133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
171423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
171523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
171623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
171723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const int									srcSize				= src.getWidth();
17183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
172023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
172123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
17223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
172323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
17243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
172523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											numFailed			= 0;
17263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
17283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
17303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
17313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
17323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
17333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
17343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
17363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
17383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
17393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
17403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
17413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
17423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
17443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
17453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
17463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
17473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
17493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
17503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
17513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
17523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
17533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
17543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
17553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
17573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
17583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
17593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
17603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
17613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		coord		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
17633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		coordDx		= triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * float(srcSize);
17643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float 	coordDy		= triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * float(srcSize);
17653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec);
17673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
17693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
17703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
17723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
17733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
17743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
17753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDxo	= triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * float(srcSize);
17773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDyo	= triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * float(srcSize);
17783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO	= tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec);
17793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
17813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
17823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
17853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
17863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
17883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
17893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
17903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
17913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
17923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
17933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
17943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
17953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
17973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
17983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
17993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
18003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
18013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
18023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture2DView&				baseView,
18033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
180441920d7e0d1833907249009d156f6eb2361df97eJarkko Pöyry							  const ReferenceParams&				sampleParams,
18053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
18063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
18073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
18083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
18093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
18103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
18113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
181223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
18130d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture2DView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
18143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
181523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
181623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
18173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
181823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
181923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
182023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
182123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
18223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
182423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
182523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
182623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
18273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
182823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
18293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
183023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											numFailed			= 0;
18313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
18333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
18353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
18363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
18373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
18383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
18393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
18413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
18433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
18443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
18453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
18463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
18473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
18493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
18503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
18513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
18523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
18543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
18553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
18563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
18573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
18583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
18593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
18603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
18623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
18633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
18643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
18653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
18663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
18683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
18693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
18703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
18713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
18723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
18733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
18753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
18773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
18783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
18803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
18813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
18823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
18833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
18853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
18863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
18873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
18883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
18893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
18913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
18923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
18933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
18953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
18963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
18973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
18983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
18993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
19003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
19013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
19023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
19033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
19043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
19073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
19103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
19113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture1DView&				src,
19123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
19133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
19143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
19153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
19163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
19173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
19193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
19203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
19213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
19223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
19243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
19263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
19273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
19303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
19323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
19333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
19373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
19383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
19413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
19433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
19463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
19473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture2DView&				src,
19483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
19493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
19503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
19513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
19523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
19533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
19553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
19563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
19573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
19583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
19603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
19623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
19633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
19663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
19683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
19693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
19713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
19723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
19733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
19743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
19753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
19773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
19793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
19803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
19813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
19823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
19833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
19843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
19853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::TextureCubeView&			baseView,
19863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
19873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
19883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
19893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
19903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
19913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
19923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
19933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
19943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
199523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
19960d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::TextureCubeView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
19973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
199823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
199923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
200023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
20013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
200223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
200323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
200423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
200523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const int									srcSize				= src.getSize();
20063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
200823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
200923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
201023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
201123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
20123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
201323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
20143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
201523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									posEps				= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
20163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
201723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											numFailed			= 0;
20183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
20203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
20223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
20233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
20243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
20253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// \note Not strictly allowed by spec, but implementations do this in practice.
20273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1, -1),
20283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1, +1),
20293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1, -1),
2030e8ef296162c99669d786b805a148b9a3e8ae5831Pyry Haulos		tcu::Vec2(+1, +1),
20313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
20323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
20343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
20363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
20373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
20383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
20393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
20403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
20423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
20433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
20443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
20453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
20473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
20483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
20493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
20503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
20513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
20523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
20533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2054aee7e15843cfe2a16c332598bbee8eaf3de351d3Pyry Haulos				const bool		tri0	= (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f;
2055aee7e15843cfe2a16c332598bbee8eaf3de351d3Pyry Haulos				const bool		tri1	= (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f;
20563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				bool			isOk	= false;
20583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(tri0 || tri1);
20603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Pixel can belong to either of the triangles if it lies close enough to the edge.
20623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
20633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
20643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triWx	= triNdx ? dstW - wx : wx;
20653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triWy	= triNdx ? dstH - wy : wy;
20663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triNx	= triNdx ? 1.0f - nx : nx;
20673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		triNy	= triNdx ? 1.0f - ny : ny;
20683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
20703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
20713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
20723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
20733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
20743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
20753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
20763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
20773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
20783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
20803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Compute lod bounds across lodOffsets range.
20823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
20833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
20843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
20853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
20863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		nxo		= wxo/dstW;
20873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const float		nyo		= wyo/dstH;
20883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
20893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
20903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
20913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
20923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
20933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
20943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
20953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
20963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
20973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry													 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
20983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
20993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
21013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
21023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
21033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
21053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix))
21073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
21083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						isOk = true;
21093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
21103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
21113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
21123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
21143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
21153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
21163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
21173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
21183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
21193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
21203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
21233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
21263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
21273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::TextureCubeView&			src,
21283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
21293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
21303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
21313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
21323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
21333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
21353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
21363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
21373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
21383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
21403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2141d81a5c316e936b6ff090e37743afbde12cfa3321Jarkko Pöyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
21423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
21433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
21453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
21463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
21483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
21493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
21513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
21523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
21533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
21543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
21553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
21573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
21593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
21603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
21623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
21633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
21643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
21653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::Texture3DView&				baseView,
21663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
21673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
21683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
21693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
21703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
21713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
21723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
21733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
21743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
217523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
21760d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture3DView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
21773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
217823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
217923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
218023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
21813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
218223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
218323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
218423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
218523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec3							srcSize				= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
21863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
218823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
218923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
219023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
219123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
21923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
219323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
21943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
219523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									posEps				= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
2196b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
219723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											numFailed			= 0;
21983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
21993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
22003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
22023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
22033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
22043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
22053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
22063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
22083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
22103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
22113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
22123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
22133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
22143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
22163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
22173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
22183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
22193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
22213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
22223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
22233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
22243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
22253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
22263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
22273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2228aee7e15843cfe2a16c332598bbee8eaf3de351d3Pyry Haulos				const bool		tri0	= (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f;
2229aee7e15843cfe2a16c332598bbee8eaf3de351d3Pyry Haulos				const bool		tri1	= (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f;
22303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2231b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				bool			isOk	= false;
22323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				DE_ASSERT(tri0 || tri1);
22343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2235b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				// Pixel can belong to either of the triangles if it lies close enough to the edge.
2236b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
22373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2238b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triWx	= triNdx ? dstW - wx : wx;
2239b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triWy	= triNdx ? dstH - wy : wy;
2240b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triNx	= triNdx ? 1.0f - nx : nx;
2241b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const float		triNy	= triNdx ? 1.0f - ny : ny;
22423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2243b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
2244b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
2245b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
2246b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec3	coordDx		= tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
2247b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
2248b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
2249b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec3	coordDy		= tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
2250b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
2251b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos															triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
22523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2253b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDx.z(), coordDy.x(), coordDy.y(), coordDy.z(), lodPrec);
22543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2255b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					// Compute lod bounds across lodOffsets range.
2256b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
2257b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					{
2258b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
2259b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
2260b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		nxo		= wxo/dstW;
2261b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const float		nyo		= wyo/dstH;
2262b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2263b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const tcu::Vec3	coordDxo	= tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
2264b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
2265b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
2266b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const tcu::Vec3	coordDyo	= tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
2267b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
2268b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos																triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
2269b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDxo.z(), coordDyo.x(), coordDyo.y(), coordDyo.z(), lodPrec);
2270b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2271b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
2272b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
2273b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					}
2274b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2275b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
2276b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos
2277b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix))
2278b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					{
2279b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						isOk = true;
2280b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos						break;
2281b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos					}
2282b9df7b5d58961270c55c87000a38a8ccbbdc19e9Pyry Haulos				}
22833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
22853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
22863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
22873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
22883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
22893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
22903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
22913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
22923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
22943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
22953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
22963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
22973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
22983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture3DView&				src,
22993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
23003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
23013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
23023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
23033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
23043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
23063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
23073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
23083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
23093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
23113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
23133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
23143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
23163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
23173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
23193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
23203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
23223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
23243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
23253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
23263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
23283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
23303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
23313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
23333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
23343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
23353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
233623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry							  const tcu::Texture1DArrayView&		baseView,
23373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
23383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
23393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
23403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
23413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
23423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
23433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
23443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
23453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
234623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
23470d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture1DArrayView				src					= getEffectiveTextureView(baseView, srcLevelStorage, sampleParams.sampler);
234823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
234923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
235023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
23513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
235223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
235323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
235423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
235523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									srcSize				= float(src.getWidth()); // For lod computation, thus #layers is ignored.
23563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
235823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
235923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
236023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
23613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
236223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
23633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
236423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											numFailed			= 0;
23653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
23673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
23693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
23703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
23713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
23723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
23733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
23753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
23773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
23783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
23793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
23803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
23813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
23833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
23843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
23853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
23863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
23883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
23893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
23903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
23913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
23923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
23933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
23943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
23953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
23963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
23973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
23983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
23993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
24003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coord	(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
24023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
24033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float	coordDx		= triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * srcSize;
24043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float	coordDy		= triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * srcSize;
24053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec);
24073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
24093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
24103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
24123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
24133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
24143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
24153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDxo		= triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * srcSize;
24173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float	coordDyo		= triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * srcSize;
24183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec);
24193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
24213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
24223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
24253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
24263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
24283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
24293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
24303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
24313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
24323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
24333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
24343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
24353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
24373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
24383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
24403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
24413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
24423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
244323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry							  const tcu::Texture2DArrayView&		baseView,
24443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const float*							texCoord,
24453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const ReferenceParams&				sampleParams,
24463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
24473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
24483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							  qpWatchDog*							watchDog)
24493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
24503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
24513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
24523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
245323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
24540d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::Texture2DArrayView				src					= getEffectiveTextureView(baseView, srcLevelStorage, sampleParams.sampler);
245523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry
245623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
245723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
245823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
24593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
246023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
246123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
246223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
246323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								srcSize				= tcu::IVec2(src.getWidth(), src.getHeight()).asFloat(); // For lod computation, thus #layers is ignored.
24643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
246623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
246723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
246823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
246923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
24703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
247123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
24723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
247323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											numFailed			= 0;
24743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
24763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
24783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
24793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
24803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
24813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
24823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
24843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
24863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
24873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
24883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (watchDog)
24893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			qpWatchDog_touch(watchDog);
24903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
24923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
24933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
24943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
24953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
24963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
24973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
24983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
24993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
25003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
25013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
25023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
25033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
25053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
25063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
25073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
25083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
25093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
25113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
25123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
25133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
25143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize;
25153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
25163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize;
25173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
25193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
25213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
25223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
25233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
25243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
25253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
25263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
25273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
25293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize;
25303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
25313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize;
25323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
25333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
25353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
25363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
25373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
25393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
25403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
25423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
25433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
25443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
25453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
25463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
25473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
25483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
25513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
25543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
25553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture1DArrayView&		src,
25563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
25573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
25583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
25593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
25603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
25613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
25633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
25643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
25653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
25663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
25683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
25703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
25713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
25733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
25743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
25763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
25773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
25793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
25803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
25813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
25823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
25833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
25853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
25873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
25883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
25893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
25903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
25913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::Texture2DArrayView&		src,
25923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const float*							texCoord,
25933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const ReferenceParams&				sampleParams,
25943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
25953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
25963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
25973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
25983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
25993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
26003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
26013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailedPixels;
26023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
26043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
26063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
26073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
26093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
26103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
26123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
26133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
26143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numFailedPixels > 0)
26153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
26163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
26178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
26188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
26198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	log << TestLog::EndImageSet;
26218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return numFailedPixels == 0;
26238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
26248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry//! Verifies texture lookup results and returns number of failed pixels.
26268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyryint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
26278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::ConstPixelBufferAccess&	reference,
26288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::PixelBufferAccess&			errorMask,
26298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::TextureCubeArrayView&		baseView,
26308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const float*							texCoord,
26318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const ReferenceParams&				sampleParams,
26328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::LookupPrecision&			lookupPrec,
26338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::IVec4&						coordBits,
26348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  const tcu::LodPrecision&				lodPrec,
26358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry							  qpWatchDog*							watchDog)
26368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
26378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
26388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
26398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
264023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
26410d61ad28c122cede72a061c4b8346a176b245b69Jarkko Pöyry	const tcu::TextureCubeArrayView				src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
26428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
264323da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
264423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
264523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
264623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec4								qq					= tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
26478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
264823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
264923da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstW				= float(dstSize.x());
265023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									dstH				= float(dstSize.y());
265123da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const int									srcSize				= src.getSize();
26528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	// Coordinates per triangle.
265423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
265523da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
265623da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
265723da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triQ[2]				= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
265823da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
26598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
266023da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
26618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
266223da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	const float									posEps				= 1.0f / float((1<<4) + 1); // ES3 requires at least 4 subpixel bits.
26638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
266423da2952459e6df3511da00f2a6c548a1b442c92Jarkko Pöyry	int											numFailed			= 0;
26658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
26678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
26688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(-1,  0),
26698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(+1,  0),
26708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2( 0, -1),
26718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2( 0, +1),
26728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// \note Not strictly allowed by spec, but implementations do this in practice.
26748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(-1, -1),
26758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(-1, +1),
26768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		tcu::Vec2(+1, -1),
26772e736e5cc21486837e98cae3c9303751f9a15c79Pyry Haulos		tcu::Vec2(+1, +1),
26788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	};
26798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
26818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
26838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
26848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		// Ugly hack, validation can take way too long at the moment.
26858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		if (watchDog)
26868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			qpWatchDog_touch(watchDog);
26878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
26898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		{
26908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
26918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
26928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
26938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			// Try comparison to ideal reference first, and if that fails use slower verificator.
26948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
26958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			{
26968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		wx		= (float)px + 0.5f;
26978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		wy		= (float)py + 0.5f;
26988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		nx		= wx / dstW;
26998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const float		ny		= wy / dstH;
27008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool		tri0	= nx + ny - posEps <= 1.0f;
27028852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				const bool		tri1	= nx + ny + posEps >= 1.0f;
27038852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27048852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				bool			isOk	= false;
27058852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27068852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				DE_ASSERT(tri0 || tri1);
27078852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27088852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				// Pixel can belong to either of the triangles if it lies close enough to the edge.
27098852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
27108852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
27118852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triWx		= triNdx ? dstW - wx : wx;
27128852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triWy		= triNdx ? dstH - wy : wy;
27138852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triNx		= triNdx ? 1.0f - nx : nx;
27148852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const float		triNy		= triNdx ? 1.0f - ny : ny;
27158852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27168852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec4	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
27178852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
27188852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy),
27198852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 projectedTriInterpolate(triQ[triNdx], triW[triNdx], triNx, triNy));
27208852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
27218852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
27228852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
27238852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
27248852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
27258852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry												 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
27268852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27278852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord.toWidth<3>(), coordDx, coordDy, srcSize, lodPrec);
27288852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27298852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					// Compute lod bounds across lodOffsets range.
27308852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
27318852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					{
27328852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		wxo			= triWx + lodOffsets[lodOffsNdx].x();
27338852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		wyo			= triWy + lodOffsets[lodOffsNdx].y();
27348852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		nxo			= wxo/dstW;
27358852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const float		nyo			= wyo/dstH;
27368852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27378852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
27388852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
27398852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
27408852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
27418852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
27428852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
27438852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
27448852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
27458852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry													 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
27468852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
27478852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27488852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
27498852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
27508852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					}
27518852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27528852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
27538852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27548852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coordBits, coord, clampedLod, resPix))
27558852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					{
27568852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						isOk = true;
27578852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						break;
27588852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					}
27598852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
27608852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27618852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				if (!isOk)
27628852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				{
27638852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
27648852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry					numFailed += 1;
27658852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry				}
27668852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry			}
27678852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		}
27688852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	}
27698852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27708852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	return numFailed;
27718852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry}
27728852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27738852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyrybool verifyTextureResult (tcu::TestContext&						testCtx,
27748852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::ConstPixelBufferAccess&	result,
27758852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::TextureCubeArrayView&		src,
27768852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const float*							texCoord,
27778852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const ReferenceParams&				sampleParams,
27788852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::LookupPrecision&			lookupPrec,
27798852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::IVec4&						coordBits,
27808852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::LodPrecision&				lodPrec,
27818852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry						  const tcu::PixelFormat&				pixelFormat)
27828852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry{
27838852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::TestLog&	log				= testCtx.getLog();
27848852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::Surface	reference		(result.getWidth(), result.getHeight());
27858852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
27868852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	int				numFailedPixels;
27878852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27888852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
27898852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27908852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	sampleTexture(SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
27918852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, coordBits, lodPrec, testCtx.getWatchDog());
27928852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27938852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (numFailedPixels > 0)
27948852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
27958852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27968852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	log << TestLog::ImageSet("VerifyResult", "Verification result")
27978852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		<< TestLog::Image("Rendered", "Rendered image", result);
27988852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry
27998852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	if (numFailedPixels > 0)
28008852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry	{
28018852c82a1ffa4760985c17cc6875d5d521daf343Jarkko Poyry		log << TestLog::Image("Reference", "Ideal reference image", reference)
28023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
28033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
28043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	log << TestLog::EndImageSet;
28063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailedPixels == 0;
28083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
28093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Shadow lookup verification
28113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
28133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::ConstPixelBufferAccess&	reference,
28143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::PixelBufferAccess&		errorMask,
28153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Texture2DView&			src,
28163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const float*							texCoord,
28173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const ReferenceParams&				sampleParams,
28183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TexComparePrecision&		comparePrec,
28193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::LodPrecision&				lodPrec,
28203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Vec3&						nonShadowThreshold)
28213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
28223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
28233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
28243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
28263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
28273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
28293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
28303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
28313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
28323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
28343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
28353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
28363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
28373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
28393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
28413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
28433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
28453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
28463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
28473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
28483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
28493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
28513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
28533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
28543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
28553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
28563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= result.getPixel(px, py);
28573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= reference.getPixel(px, py);
28583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Other channels should trivially match to reference.
28603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
28613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
28623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
28633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
28643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
28653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
28663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2867a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// Reference result is known to be a valid result, we can
2868a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// skip verification if thes results are equal
2869a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			if (resPix.x() != refPix.x())
28703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
28713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
28723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
28733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
28743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
28753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
28773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
28783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
28793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
28803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
28813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
28833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
28843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
28853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
28863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
28873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
28883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
28903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
28923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
28933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
28943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
28953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
28963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
28973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
28983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
28993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
29003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
29013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
29023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
29033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
29043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
29063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
29073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
29083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
29103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
29113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
29133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
29143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
29153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
29163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
29173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
29183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
29193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
29203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
29223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
29233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29243c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
29253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::ConstPixelBufferAccess&	reference,
29263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::PixelBufferAccess&		errorMask,
29273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TextureCubeView&			src,
29283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const float*							texCoord,
29293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const ReferenceParams&				sampleParams,
29303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TexComparePrecision&		comparePrec,
29313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::LodPrecision&				lodPrec,
29323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Vec3&						nonShadowThreshold)
29333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
29343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
29353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
29363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
29383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
29393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
29403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
29423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
29433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
29443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			srcSize			= src.getSize();
29453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates per triangle.
29473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
29483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
29493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
29503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
29513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
29533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
29553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
29573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
29593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
29603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
29613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
29623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
29633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
29653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
29673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
29683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
29693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
29703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= result.getPixel(px, py);
29713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= reference.getPixel(px, py);
29723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// Other channels should trivially match to reference.
29743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
29753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
29763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
29773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
29783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
29793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
29803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2981a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// Reference result is known to be a valid result, we can
2982a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// skip verification if thes results are equal
2983a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			if (resPix.x() != refPix.x())
29843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
29853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
29863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
29873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
29883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
29893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
29913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
29923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
29933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
29943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
29953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
29963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
29973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
29983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
29993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
30003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
30013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
30023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
30033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
30043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
30053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
30073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
30093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
30103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
30123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
30133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
30143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
30153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
30173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
30183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
30193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
30203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
30213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
30223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
30233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
30243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry												 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
30253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
30263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
30283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
30293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
30303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
30323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
30333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
30353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
30363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
30373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
30383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
30393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
30403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
30413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
30423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
30443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
30453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30463c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
30473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::ConstPixelBufferAccess&	reference,
30483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::PixelBufferAccess&		errorMask,
30493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Texture2DArrayView&		src,
30503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const float*							texCoord,
30513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const ReferenceParams&				sampleParams,
30523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::TexComparePrecision&		comparePrec,
30533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::LodPrecision&				lodPrec,
30543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const tcu::Vec3&						nonShadowThreshold)
30553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
30563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
30573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
30583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
30603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
30613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
30623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
30643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstW			= float(dstSize.x());
30653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float			dstH			= float(dstSize.y());
30663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
30673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Coordinates and lod per triangle.
30693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
30703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
30713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
30723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
30733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
30753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					numFailed		= 0;
30773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Vec2 lodOffsets[] =
30793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(-1,  0),
30813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2(+1,  0),
30823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, -1),
30833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec2( 0, +1),
30843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
30853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::clear(errorMask, tcu::RGBA::green.toVec());
30873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
30883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int py = 0; py < result.getHeight(); py++)
30893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
30903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int px = 0; px < result.getWidth(); px++)
30913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
30923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	resPix	= result.getPixel(px, py);
30933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::Vec4	refPix	= reference.getPixel(px, py);
30943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3095a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// Other channels should trivially match to reference.
30963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
30973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
30983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
30993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				numFailed += 1;
31003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				continue;
31013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
31023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3103a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// Reference result is known to be a valid result, we can
3104a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			// skip verification if thes results are equal
3105a8db46533fb193367ac272296f59393ce5dd5e02Jarkko Pöyry			if (resPix.x() != refPix.x())
31063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
31073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wx		= (float)px + 0.5f;
31083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		wy		= (float)py + 0.5f;
31093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		nx		= wx / dstW;
31103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		ny		= wy / dstH;
31113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
31133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWx	= triNdx ? dstW - wx : wx;
31143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triWy	= triNdx ? dstH - wy : wy;
31153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNx	= triNdx ? 1.0f - nx : nx;
31163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const float		triNy	= triNdx ? 1.0f - ny : ny;
31173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
31193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
31203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
31213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
31223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
31233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
31243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
31253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
31273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Compute lod bounds across lodOffsets range.
31293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
31303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
31313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
31323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
31333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nxo		= wxo/dstW;
31343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const float		nyo		= wyo/dstH;
31353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
31373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
31383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
31393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
31403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
31413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
31433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
31443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
31453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
31473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
31483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isOk)
31503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
31513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					errorMask.setPixel(tcu::RGBA::red.toVec(), px, py);
31523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					numFailed += 1;
31533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
31543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
31553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
31563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
31593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Mipmap generation comparison.
31623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31633c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int compareGenMipmapBilinear (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
31643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
31653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
31663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstW		= float(dst.getWidth());
31683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstH		= float(dst.getHeight());
31693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcW		= float(src.getWidth());
31703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcH		= float(src.getHeight());
31713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailed	= 0;
31723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Translation to lookup verification parameters.
31743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
31753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */);
31763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::LookupPrecision	lookupPrec;
31773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorThreshold	= precision.colorThreshold;
31793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorMask		= precision.colorMask;
31803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.coordBits		= tcu::IVec3(22);
31813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.uvwBits			= precision.filterBits;
31823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
31843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < dst.getWidth(); x++)
31853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
31863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	result	= dst.getPixel(x, y);
31873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cx		= (float(x)+0.5f) / dstW * srcW;
31883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cy		= (float(y)+0.5f) / dstH * srcH;
31893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		isOk	= tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result);
31903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		errorMask.setPixel(isOk ? tcu::RGBA::green.toVec() : tcu::RGBA::red.toVec(), x, y);
31923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
31933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numFailed += 1;
31943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
31953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
31973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
31983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
31993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int compareGenMipmapBox (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
32003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
32023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstW		= float(dst.getWidth());
32043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstH		= float(dst.getHeight());
32053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcW		= float(src.getWidth());
32063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcH		= float(src.getHeight());
32073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailed	= 0;
32083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Translation to lookup verification parameters.
32103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
32113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry										 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */);
32123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tcu::LookupPrecision	lookupPrec;
32133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorThreshold	= precision.colorThreshold;
32153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.colorMask		= precision.colorMask;
32163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.coordBits		= tcu::IVec3(22);
32173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	lookupPrec.uvwBits			= precision.filterBits;
32183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
32203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < dst.getWidth(); x++)
32213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	result	= dst.getPixel(x, y);
32233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cx		= deFloatFloor(float(x) / dstW * srcW) + 1.0f;
32243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		cy		= deFloatFloor(float(y) / dstH * srcH) + 1.0f;
32253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool		isOk	= tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result);
32263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		errorMask.setPixel(isOk ? tcu::RGBA::green.toVec() : tcu::RGBA::red.toVec(), x, y);
32283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
32293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numFailed += 1;
32303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
32333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int compareGenMipmapVeryLenient (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
32363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
32383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(precision);
32393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstW		= float(dst.getWidth());
32413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		dstH		= float(dst.getHeight());
32423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcW		= float(src.getWidth());
32433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		srcH		= float(src.getHeight());
32443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numFailed	= 0;
32453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int y = 0; y < dst.getHeight(); y++)
32473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int x = 0; x < dst.getWidth(); x++)
32483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4	result	= dst.getPixel(x, y);
32503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		minX		= deFloorFloatToInt32(float(x-0.5f) / dstW * srcW);
32513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		minY		= deFloorFloatToInt32(float(y-0.5f) / dstH * srcH);
32523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		maxX		= deCeilFloatToInt32(float(x+1.5f) / dstW * srcW);
32533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		maxY		= deCeilFloatToInt32(float(y+1.5f) / dstH * srcH);
32543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Vec4		minVal, maxVal;
32553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool			isOk;
32563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(minX < maxX && minY < maxY);
32583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ky = minY; ky <= maxY; ky++)
32603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
32613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int kx = minX; kx <= maxX; kx++)
32623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
32633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		sx		= de::clamp(kx, 0, src.getWidth()-1);
32643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int		sy		= de::clamp(ky, 0, src.getHeight()-1);
32653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const tcu::Vec4	sample	= src.getPixel(sx, sy);
32663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (ky == minY && kx == minX)
32683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
32693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					minVal = sample;
32703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					maxVal = sample;
32713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
32723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
32733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
32743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					minVal = min(sample, minVal);
32753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					maxVal = max(sample, maxVal);
32763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
32773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
32783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
32793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		isOk = boolAll(logicalAnd(lessThanEqual(minVal, result), lessThanEqual(result, maxVal)));
32813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		errorMask.setPixel(isOk ? tcu::RGBA::green.toVec() : tcu::RGBA::red.toVec(), x, y);
32833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!isOk)
32843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numFailed += 1;
32853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
32863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numFailed;
32883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
32893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32903c827367444ee418f129b2c238299f49d3264554Jarkko PoyryqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::Texture2D& resultTexture, const tcu::Texture2D& level0Reference, const GenMipmapPrecision& precision)
32913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
32923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpTestResult result = QP_TEST_RESULT_PASS;
32933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Special comparison for level 0.
32953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
32963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		threshold	= select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask);
32973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			level0Ok	= tcu::floatThresholdCompare(log, "Level0", "Level 0", level0Reference.getLevel(0), resultTexture.getLevel(0), threshold, tcu::COMPARE_LOG_RESULT);
32983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
32993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!level0Ok)
33003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "ERROR: Level 0 comparison failed!" << TestLog::EndMessage;
33023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_FAIL;
33033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++)
33073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ConstPixelBufferAccess	src			= resultTexture.getLevel(levelNdx-1);
33093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::ConstPixelBufferAccess	dst			= resultTexture.getLevel(levelNdx);
33103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tcu::Surface						errorMask	(dst.getWidth(), dst.getHeight());
33113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool								levelOk		= false;
33123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Try different comparisons in quality order.
33143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision);
33183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numFailed == 0)
33193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelOk = true;
33203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
33213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "WARNING: Level " << levelNdx << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
33223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision);
33273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numFailed == 0)
33283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelOk = true;
33293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
33303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "WARNING: Level " << levelNdx << " comparison to box method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
33313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// At this point all high-quality methods have been used.
33343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk && result == QP_TEST_RESULT_PASS)
33353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_QUALITY_WARNING;
33363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision);
33403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (numFailed == 0)
33413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				levelOk = true;
33423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
33433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Message << "ERROR: Level " << levelNdx << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << TestLog::EndMessage;
33443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_FAIL;
33483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::ImageSet(string("Level") + de::toString(levelNdx), string("Level ") + de::toString(levelNdx) + " result")
33503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			<< TestLog::Image("Result", "Result", dst);
33513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!levelOk)
33533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Image("ErrorMask", "Error mask", errorMask);
33543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		log << TestLog::EndImageSet;
33563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
33593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
33603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33613c827367444ee418f129b2c238299f49d3264554Jarkko PoyryqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::TextureCube& resultTexture, const tcu::TextureCube& level0Reference, const GenMipmapPrecision& precision)
33623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
33633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	qpTestResult result = QP_TEST_RESULT_PASS;
33643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const char* s_faceNames[] = { "-X", "+X", "-Y", "+Y", "-Z", "+Z" };
33663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_faceNames) == tcu::CUBEFACE_LAST);
33673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Special comparison for level 0.
33693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
33703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::CubeFace	face		= tcu::CubeFace(faceNdx);
33723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const tcu::Vec4		threshold	= select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask);
33733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const bool			level0Ok	= tcu::floatThresholdCompare(log,
33743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 ("Level0Face" + de::toString(faceNdx)).c_str(),
33753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 (string("Level 0, face ") + s_faceNames[face]).c_str(),
33763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 level0Reference.getLevelFace(0, face),
33773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 resultTexture.getLevelFace(0, face),
33783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry																	 threshold, tcu::COMPARE_LOG_RESULT);
33793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!level0Ok)
33813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::Message << "ERROR: Level 0, face " << s_faceNames[face] << " comparison failed!" << TestLog::EndMessage;
33833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			result = QP_TEST_RESULT_FAIL;
33843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
33853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
33863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++)
33883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
33893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
33903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
33913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::CubeFace					face		= tcu::CubeFace(faceNdx);
33923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const char*							faceName	= s_faceNames[face];
33933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::ConstPixelBufferAccess	src			= resultTexture.getLevelFace(levelNdx-1,	face);
33943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const tcu::ConstPixelBufferAccess	dst			= resultTexture.getLevelFace(levelNdx,		face);
33953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tcu::Surface						errorMask	(dst.getWidth(), dst.getHeight());
33963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			bool								levelOk		= false;
33973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
33983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Try different comparisons in quality order.
33993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
34013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
34023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision);
34033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numFailed == 0)
34043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levelOk = true;
34053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
34063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
34073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
34083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
34103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
34113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision);
34123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numFailed == 0)
34133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levelOk = true;
34143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
34153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName <<" comparison to box method failed, found " << numFailed << " invalid pixels." << TestLog::EndMessage;
34163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
34173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// At this point all high-quality methods have been used.
34193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk && result == QP_TEST_RESULT_PASS)
34203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result = QP_TEST_RESULT_QUALITY_WARNING;
34213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
34233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
34243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision);
34253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (numFailed == 0)
34263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					levelOk = true;
34273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
34283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					log << TestLog::Message << "ERROR: Level " << levelNdx << ", face " << faceName << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << TestLog::EndMessage;
34293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
34303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
34323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				result = QP_TEST_RESULT_FAIL;
34333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::ImageSet(string("Level") + de::toString(levelNdx) + "Face" + de::toString(faceNdx), string("Level ") + de::toString(levelNdx) + ", face " + string(faceName) + " result")
34353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				<< TestLog::Image("Result", "Result", dst);
34363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!levelOk)
34383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				log << TestLog::Image("ErrorMask", "Error mask", errorMask);
34393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			log << TestLog::EndImageSet;
34413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
34423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
34433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
34453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
34463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Logging utilities.
34483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const LogGradientFmt& fmt)
34503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
34513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str << "(R: " << fmt.valueMin->x() << " -> " << fmt.valueMax->x() << ", "
34523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   <<  "G: " << fmt.valueMin->y() << " -> " << fmt.valueMax->y() << ", "
34533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   <<  "B: " << fmt.valueMin->z() << " -> " << fmt.valueMax->z() << ", "
34543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   <<  "A: " << fmt.valueMin->w() << " -> " << fmt.valueMax->w() << ")";
34553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
34563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
34573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // TextureTestUtil
34583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // gls
34593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // deqp
3460