1c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket/*-------------------------------------------------------------------------
2c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * drawElements Quality Program OpenGL ES Utilities
3c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * ------------------------------------------------
4c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *
5c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * Copyright 2014 The Android Open Source Project
6c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *
7c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * Licensed under the Apache License, Version 2.0 (the "License");
8c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * you may not use this file except in compliance with the License.
9c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * You may obtain a copy of the License at
10c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *
11c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *      http://www.apache.org/licenses/LICENSE-2.0
12c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *
13c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * Unless required by applicable law or agreed to in writing, software
14c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * distributed under the License is distributed on an "AS IS" BASIS,
15c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * See the License for the specific language governing permissions and
17c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * limitations under the License.
18c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *
19c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *//*!
20c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * \file
21c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * \brief Utility functions and structures for texture tests. This code
22c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * is originated from the modules/glshared/glsTextureTestUtil.hpp and it
23c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket * is tightly coupled with the GLES and Vulkan texture tests!
24c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket *//*--------------------------------------------------------------------*/
25c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
26c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "gluTextureTestUtil.hpp"
27c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
28c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "tcuFloat.hpp"
29c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "tcuImageCompare.hpp"
30c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "tcuTestLog.hpp"
31c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "tcuVectorUtil.hpp"
32c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
33c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "deMath.h"
34c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include "deStringUtil.hpp"
35c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
36c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket#include <string>
37c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
38c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketusing std::string;
39c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
40c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketnamespace glu
41c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
42c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
43c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketnamespace TextureTestUtil
44c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
45c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
46c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketenum
47c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
48c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	MIN_SUBPIXEL_BITS	= 4
49c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket};
50c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
51c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter SiketSamplerType getSamplerType (tcu::TextureFormat format)
52c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
53c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	using tcu::TextureFormat;
54c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
55c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (format.type)
56c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
57c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::SIGNED_INT8:
58c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::SIGNED_INT16:
59c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::SIGNED_INT32:
60c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return SAMPLERTYPE_INT;
61c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
62c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT8:
63c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT32:
64c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT_1010102_REV:
65c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return SAMPLERTYPE_UINT;
66c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
67c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Texture formats used in depth/stencil textures.
68c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT16:
69c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT_24_8:
70c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FLOAT : SAMPLERTYPE_UINT;
71c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
72c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
73c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return SAMPLERTYPE_FLOAT;
74c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
75c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
76c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
77c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter SiketSamplerType getFetchSamplerType (tcu::TextureFormat format)
78c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
79c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	using tcu::TextureFormat;
80c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
81c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (format.type)
82c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
83c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::SIGNED_INT8:
84c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::SIGNED_INT16:
85c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::SIGNED_INT32:
86c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return SAMPLERTYPE_FETCH_INT;
87c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
88c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT8:
89c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT32:
90c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT_1010102_REV:
91c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return SAMPLERTYPE_FETCH_UINT;
92c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
93c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Texture formats used in depth/stencil textures.
94c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT16:
95c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case TextureFormat::UNSIGNED_INT_24_8:
96c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return (format.order == TextureFormat::D || format.order == TextureFormat::DS) ? SAMPLERTYPE_FETCH_FLOAT : SAMPLERTYPE_FETCH_UINT;
97c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
98c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
99c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return SAMPLERTYPE_FETCH_FLOAT;
100c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
101c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
102c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
103c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic tcu::Texture1DView getSubView (const tcu::Texture1DView& view, int baseLevel, int maxLevel)
104c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
105c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
106c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
107c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	numLevels	= clampedMax-clampedBase+1;
108c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::Texture1DView(numLevels, view.getLevels()+clampedBase);
109c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
110c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
111c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic tcu::Texture2DView getSubView (const tcu::Texture2DView& view, int baseLevel, int maxLevel)
112c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
113c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
114c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
115c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	numLevels	= clampedMax-clampedBase+1;
116c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::Texture2DView(numLevels, view.getLevels()+clampedBase);
117c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
118c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
119c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic tcu::TextureCubeView getSubView (const tcu::TextureCubeView& view, int baseLevel, int maxLevel)
120c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
121c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int							clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
122c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int							clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
123c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int							numLevels	= clampedMax-clampedBase+1;
124c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::ConstPixelBufferAccess*	levels[tcu::CUBEFACE_LAST];
125c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
126c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
127c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		levels[face] = view.getFaceLevels((tcu::CubeFace)face) + clampedBase;
128c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
129c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::TextureCubeView(numLevels, levels);
130c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
131c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
132c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic tcu::Texture3DView getSubView (const tcu::Texture3DView& view, int baseLevel, int maxLevel)
133c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
134c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
135c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
136c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	numLevels	= clampedMax-clampedBase+1;
137c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::Texture3DView(numLevels, view.getLevels()+clampedBase);
138c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
139c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
140c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic tcu::TextureCubeArrayView getSubView (const tcu::TextureCubeArrayView& view, int baseLevel, int maxLevel)
141c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
142c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedBase	= de::clamp(baseLevel, 0, view.getNumLevels()-1);
143c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	clampedMax	= de::clamp(maxLevel, clampedBase, view.getNumLevels()-1);
144c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	numLevels	= clampedMax-clampedBase+1;
145c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::TextureCubeArrayView(numLevels, view.getLevels()+clampedBase);
146c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
147c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
148c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline float linearInterpolate (float t, float minVal, float maxVal)
149c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
150c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return minVal + (maxVal - minVal) * t;
151c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
152c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
153c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline tcu::Vec4 linearInterpolate (float t, const tcu::Vec4& a, const tcu::Vec4& b)
154c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
155c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return a + (b - a) * t;
156c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
157c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
158c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline float bilinearInterpolate (float x, float y, const tcu::Vec4& quad)
159c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
160c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float w00 = (1.0f-x)*(1.0f-y);
161c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float w01 = (1.0f-x)*y;
162c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float w10 = x*(1.0f-y);
163c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float w11 = x*y;
164c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return quad.x()*w00 + quad.y()*w10 + quad.z()*w01 + quad.w()*w11;
165c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
166c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
167c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline float triangleInterpolate (float v0, float v1, float v2, float x, float y)
168c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
169c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return v0 + (v2-v0)*x + (v1-v0)*y;
170c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
171c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
172c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline float triangleInterpolate (const tcu::Vec3& v, float x, float y)
173c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
174c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return triangleInterpolate(v.x(), v.y(), v.z(), x, y);
175c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
176c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
177c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// 1D lookup LOD computation.
178c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
179c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketfloat computeLodFromDerivates (LodMode mode, float dudx, float dudy)
180c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
181c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float p = 0.0f;
182c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (mode)
183c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
184c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// \note [mika] Min and max bounds equal to exact with 1D textures
185c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_EXACT:
186c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_MIN_BOUND:
187c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_MAX_BOUND:
188c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			p = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
189c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			break;
190c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
191c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
192c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			DE_ASSERT(DE_FALSE);
193c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
194c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
195c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return deFloatLog2(p);
196c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
197c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
198c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, deInt32 srcSize, const tcu::Vec3& sq)
199c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
200c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dux	= (sq.z() - sq.x()) * (float)srcSize;
201c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float duy	= (sq.y() - sq.x()) * (float)srcSize;
202c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dx	= (float)dstSize.x();
203c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dy	= (float)dstSize.y();
204c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
205c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return computeLodFromDerivates(mode, dux/dx, duy/dy);
206c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
207c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
208c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// 2D lookup LOD computation.
209c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
210c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketfloat computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dudy, float dvdy)
211c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
212c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float p = 0.0f;
213c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (mode)
214c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
215c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_EXACT:
216c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx), deFloatSqrt(dudy*dudy + dvdy*dvdy));
217c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			break;
218c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
219c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_MIN_BOUND:
220c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_MAX_BOUND:
221c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
222c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
223c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
224c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
225c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			p = mode == LODMODE_MIN_BOUND ? de::max(mu, mv) : mu + mv;
226c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			break;
227c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
228c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
229c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
230c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			DE_ASSERT(DE_FALSE);
231c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
232c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
233c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return deFloatLog2(p);
234c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
235c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
236c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, const tcu::IVec2& srcSize, const tcu::Vec3& sq, const tcu::Vec3& tq)
237c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
238c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dux	= (sq.z() - sq.x()) * (float)srcSize.x();
239c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float duy	= (sq.y() - sq.x()) * (float)srcSize.x();
240c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvx	= (tq.z() - tq.x()) * (float)srcSize.y();
241c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvy	= (tq.y() - tq.x()) * (float)srcSize.y();
242c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dx	= (float)dstSize.x();
243c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dy	= (float)dstSize.y();
244c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
245c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return computeLodFromDerivates(mode, dux/dx, dvx/dx, duy/dy, dvy/dy);
246c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
247c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
248c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// 3D lookup LOD computation.
249c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
250c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketfloat computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dwdx, float dudy, float dvdy, float dwdy)
251c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
252c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float p = 0.0f;
253c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (mode)
254c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
255c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_EXACT:
256c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx + dwdx*dwdx), deFloatSqrt(dudy*dudy + dvdy*dvdy + dwdy*dwdy));
257c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			break;
258c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
259c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_MIN_BOUND:
260c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case LODMODE_MAX_BOUND:
261c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
262c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
263c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
264c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float mw = de::max(deFloatAbs(dwdx), deFloatAbs(dwdy));
265c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
266c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			p = mode == LODMODE_MIN_BOUND ? de::max(de::max(mu, mv), mw) : (mu + mv + mw);
267c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			break;
268c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
269c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
270c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
271c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			DE_ASSERT(DE_FALSE);
272c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
273c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
274c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return deFloatLog2(p);
275c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
276c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
277c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic float computeNonProjectedTriLod (LodMode mode, const tcu::IVec2& dstSize, const tcu::IVec3& srcSize, const tcu::Vec3& sq, const tcu::Vec3& tq, const tcu::Vec3& rq)
278c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
279c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dux	= (sq.z() - sq.x()) * (float)srcSize.x();
280c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float duy	= (sq.y() - sq.x()) * (float)srcSize.x();
281c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvx	= (tq.z() - tq.x()) * (float)srcSize.y();
282c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvy	= (tq.y() - tq.x()) * (float)srcSize.y();
283c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dwx	= (rq.z() - rq.x()) * (float)srcSize.z();
284c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dwy	= (rq.y() - rq.x()) * (float)srcSize.z();
285c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dx	= (float)dstSize.x();
286c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dy	= (float)dstSize.y();
287c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
288c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return computeLodFromDerivates(mode, dux/dx, dvx/dx, dwx/dx, duy/dy, dvy/dy, dwy/dy);
289c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
290c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
291c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline float projectedTriInterpolate (const tcu::Vec3& s, const tcu::Vec3& w, float nx, float ny)
292c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
293c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	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]);
294c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
295c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
296c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline float triDerivateX (const tcu::Vec3& s, const tcu::Vec3& w, float wx, float width, float ny)
297c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
298c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float d = w[1]*w[2]*(width*(ny - 1.0f) + wx) - w[0]*(w[2]*width*ny + w[1]*wx);
299c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	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);
300c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
301c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
302c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline float triDerivateY (const tcu::Vec3& s, const tcu::Vec3& w, float wy, float height, float nx)
303c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
304c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float d = w[1]*w[2]*(height*(nx - 1.0f) + wy) - w[0]*(w[1]*height*nx + w[2]*wy);
305c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	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);
306c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
307c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
308c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// 1D lookup LOD.
309c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& projection, float wx, float wy, float width, float height)
310c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
311c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Exact derivatives.
312c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
313c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
314c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
315c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return computeLodFromDerivates(mode, dudx, dudy);
316c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
317c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
318c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// 2D lookup LOD.
319c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic float computeProjectedTriLod (LodMode mode, const tcu::Vec3& u, const tcu::Vec3& v, const tcu::Vec3& projection, float wx, float wy, float width, float height)
320c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
321c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Exact derivatives.
322c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
323c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvdx	= triDerivateX(v, projection, wx, width, wy/height);
324c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
325c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvdy	= triDerivateY(v, projection, wy, height, wx/width);
326c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
327c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return computeLodFromDerivates(mode, dudx, dvdx, dudy, dvdy);
328c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
329c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
330c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// 3D lookup LOD.
331c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic 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)
332c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
333c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Exact derivatives.
334c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dudx	= triDerivateX(u, projection, wx, width, wy/height);
335c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvdx	= triDerivateX(v, projection, wx, width, wy/height);
336c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dwdx	= triDerivateX(w, projection, wx, width, wy/height);
337c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dudy	= triDerivateY(u, projection, wy, height, wx/width);
338c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dvdy	= triDerivateY(v, projection, wy, height, wx/width);
339c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float dwdy	= triDerivateY(w, projection, wy, height, wx/width);
340c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
341c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return computeLodFromDerivates(mode, dudx, dvdx, dwdx, dudy, dvdy, dwdy);
342c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
343c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
344c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline tcu::Vec4 execSample (const tcu::Texture1DView& src, const ReferenceParams& params, float s, float lod)
345c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
346c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.samplerType == SAMPLERTYPE_SHADOW)
347c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, lod), 0.0, 0.0, 1.0f);
348c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
349c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return src.sample(params.sampler, s, lod);
350c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
351c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
352c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline tcu::Vec4 execSample (const tcu::Texture2DView& src, const ReferenceParams& params, float s, float t, float lod)
353c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
354c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.samplerType == SAMPLERTYPE_SHADOW)
355c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f);
356c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
357c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return src.sample(params.sampler, s, t, lod);
358c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
359c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
360c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline tcu::Vec4 execSample (const tcu::TextureCubeView& src, const ReferenceParams& params, float s, float t, float r, float lod)
361c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
362c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.samplerType == SAMPLERTYPE_SHADOW)
363c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f);
364c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
365c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return src.sample(params.sampler, s, t, r, lod);
366c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
367c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
368c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline tcu::Vec4 execSample (const tcu::Texture2DArrayView& src, const ReferenceParams& params, float s, float t, float r, float lod)
369c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
370c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.samplerType == SAMPLERTYPE_SHADOW)
371c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, lod), 0.0, 0.0, 1.0f);
372c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
373c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return src.sample(params.sampler, s, t, r, lod);
374c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
375c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
376c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline tcu::Vec4 execSample (const tcu::TextureCubeArrayView& src, const ReferenceParams& params, float s, float t, float r, float q, float lod)
377c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
378c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.samplerType == SAMPLERTYPE_SHADOW)
379c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, r, q, lod), 0.0, 0.0, 1.0f);
380c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
381c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return src.sample(params.sampler, s, t, r, q, lod);
382c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
383c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
384c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic inline tcu::Vec4 execSample (const tcu::Texture1DArrayView& src, const ReferenceParams& params, float s, float t, float lod)
385c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
386c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.samplerType == SAMPLERTYPE_SHADOW)
387c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return tcu::Vec4(src.sampleCompare(params.sampler, params.ref, s, t, lod), 0.0, 0.0, 1.0f);
388c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
389c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return src.sample(params.sampler, s, t, lod);
390c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
391c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
392c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params)
393c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
394c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
395c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
396c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture1DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
397c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
398c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
399c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
400c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
401c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											srcSize				= src.getWidth();
402c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
403c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
404c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
405c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias, params.minLod, params.maxLod),
406c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias, params.minLod, params.maxLod) };
407c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
408c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
409c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
410c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int x = 0; x < dst.getWidth(); x++)
411c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
412c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
413c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
414c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
415c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
416c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triX	= triNdx ? 1.0f-xf : xf;
417c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triY	= triNdx ? 1.0f-yf : yf;
418c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
419c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
420c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= triLod[triNdx];
421c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
422c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, s, lod) * params.colorScale + params.colorBias, x, y);
423c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
424c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
425c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
426c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
427c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
428c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
429c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
430c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
431c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture2DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
432c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
433c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
434c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
435c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
436c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec2									srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
437c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
438c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
439c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
440c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
441c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod),
442c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) };
443c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
444c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
445c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
446c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int x = 0; x < dst.getWidth(); x++)
447c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
448c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
449c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
450c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
451c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
452c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triX	= triNdx ? 1.0f-xf : xf;
453c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triY	= triNdx ? 1.0f-yf : yf;
454c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
455c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
456c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
457c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= triLod[triNdx];
458c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
459c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y);
460c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
461c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
462c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
463c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
464c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureProjected (const tcu::SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params)
465c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
466c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
467c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
468c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture1DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
469c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
470c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
471c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										dstW				= (float)dst.getWidth();
472c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										dstH				= (float)dst.getHeight();
473c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
474c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4									uq					= sq * (float)src.getWidth();
475c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
476c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
477c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
478c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
479c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
480c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < dst.getHeight(); py++)
481c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
482c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < dst.getWidth(); px++)
483c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
484c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	wx		= (float)px + 0.5f;
485c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	wy		= (float)py + 0.5f;
486c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	nx		= wx / dstW;
487c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	ny		= wy / dstH;
488c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
489c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
490c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triWx	= triNdx ? dstW - wx : wx;
491c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triWy	= triNdx ? dstH - wy : wy;
492c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triNx	= triNdx ? 1.0f - nx : nx;
493c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triNy	= triNdx ? 1.0f - ny : ny;
494c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
495c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
496c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
497c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							+ lodBias;
498c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
499c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, s, lod) * params.colorScale + params.colorBias, px, py);
500c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
501c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
502c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
503c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
504c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureProjected (const tcu::SurfaceAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
505c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
506c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
507c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
508c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture2DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
509c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
510c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
511c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										dstW				= (float)dst.getWidth();
512c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										dstH				= (float)dst.getHeight();
513c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
514c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4									uq					= sq * (float)src.getWidth();
515c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4									vq					= tq * (float)src.getHeight();
516c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
517c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
518c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
519c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
520c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triV[2]				= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
521c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
522c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
523c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < dst.getHeight(); py++)
524c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
525c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < dst.getWidth(); px++)
526c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
527c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	wx		= (float)px + 0.5f;
528c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	wy		= (float)py + 0.5f;
529c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	nx		= wx / dstW;
530c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	ny		= wy / dstH;
531c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
532c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
533c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triWx	= triNdx ? dstW - wx : wx;
534c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triWy	= triNdx ? dstH - wy : wy;
535c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triNx	= triNdx ? 1.0f - nx : nx;
536c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triNy	= triNdx ? 1.0f - ny : ny;
537c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
538c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
539c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	t		= projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy);
540c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
541c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							+ lodBias;
542c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
543c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, px, py);
544c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
545c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
546c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
547c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
548c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture2DView& src, const float* texCoord, const ReferenceParams& params)
549c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
550c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture2DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
551c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
552c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
553c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
554c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.flags & ReferenceParams::PROJECTED)
555c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		sampleTextureProjected(dst, view, sq, tq, params);
556c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
557c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		sampleTextureNonProjected(dst, view, sq, tq, params);
558c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
559c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
560c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture1DView& src, const float* texCoord, const ReferenceParams& params)
561c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
562c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture1DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
563c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
564c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
565c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.flags & ReferenceParams::PROJECTED)
566c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		sampleTextureProjected(dst, view, sq, params);
567c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
568c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		sampleTextureNonProjected(dst, view, sq, params);
569c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
570c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
571c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic float computeCubeLodFromDerivates (LodMode lodMode, const tcu::Vec3& coord, const tcu::Vec3& coordDx, const tcu::Vec3& coordDy, const int faceSize)
572c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
573c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::CubeFace	face	= tcu::selectCubeFace(coord);
574c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int					maNdx	= 0;
575c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int					sNdx	= 0;
576c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int					tNdx	= 0;
577c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
578c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// \note Derivate signs don't matter when computing lod
579c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (face)
580c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
581c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_X:
582c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_X: maNdx = 0; sNdx = 2; tNdx = 1; break;
583c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Y:
584c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Y: maNdx = 1; sNdx = 0; tNdx = 2; break;
585c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Z:
586c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Z: maNdx = 2; sNdx = 0; tNdx = 1; break;
587c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
588c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			DE_ASSERT(DE_FALSE);
589c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
590c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
591c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
592c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		sc		= coord[sNdx];
593c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		tc		= coord[tNdx];
594c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		ma		= de::abs(coord[maNdx]);
595c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		scdx	= coordDx[sNdx];
596c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		tcdx	= coordDx[tNdx];
597c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		madx	= de::abs(coordDx[maNdx]);
598c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		scdy	= coordDy[sNdx];
599c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		tcdy	= coordDy[tNdx];
600c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		mady	= de::abs(coordDy[maNdx]);
601c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		dudx	= float(faceSize) * 0.5f * (scdx*ma - sc*madx) / (ma*ma);
602c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		dvdx	= float(faceSize) * 0.5f * (tcdx*ma - tc*madx) / (ma*ma);
603c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		dudy	= float(faceSize) * 0.5f * (scdy*ma - sc*mady) / (ma*ma);
604c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		dvdy	= float(faceSize) * 0.5f * (tcdy*ma - tc*mady) / (ma*ma);
605c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
606c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return computeLodFromDerivates(lodMode, dudx, dvdx, dudy, dvdy);
607c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
608c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
609c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
610c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureCube (const tcu::SurfaceAccess& dst, const tcu::TextureCubeView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
611c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
612c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
613c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
614c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::TextureCubeView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
615c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
616c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
617c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
618c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
619c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int									srcSize				= src.getSize();
620c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
621c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates per triangle.
622c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
623c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
624c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
625c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
626c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
627c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									lodBias				((params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f);
628c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
629c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < dst.getHeight(); py++)
630c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
631c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < dst.getWidth(); px++)
632c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
633c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		wx		= (float)px + 0.5f;
634c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		wy		= (float)py + 0.5f;
635c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		nx		= wx / dstW;
636c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		ny		= wy / dstH;
637c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
638c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
639c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		triNx	= triNdx ? 1.0f - nx : nx;
640c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		triNy	= triNdx ? 1.0f - ny : ny;
641c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
642c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec3	coord		(triangleInterpolate(triS[triNdx], triNx, triNy),
643c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 triangleInterpolate(triT[triNdx], triNx, triNy),
644c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 triangleInterpolate(triR[triNdx], triNx, triNy));
645c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
646c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
647c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
648c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
649c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
650c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
651c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
652c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		lod			= de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, srcSize) + lodBias, params.minLod, params.maxLod);
653c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
654c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), lod) * params.colorScale + params.colorBias, px, py);
655c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
656c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
657c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
658c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
659c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::TextureCubeView& src, const float* texCoord, const ReferenceParams& params)
660c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
661c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::TextureCubeView	view	= getSubView(src, params.baseLevel, params.maxLevel);
662c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
663c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
664c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				rq		= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
665c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
666c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return sampleTextureCube(dst, view, sq, tq, rq, params);
667c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
668c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
669c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture2DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
670c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
671c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
672c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
673c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture2DArrayView				src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
674c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
675c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
676c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
677c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
678c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec2									srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
679c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
680c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
681c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
682c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
683c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
684c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod),
685c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) };
686c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
687c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
688c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
689c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int x = 0; x < dst.getWidth(); x++)
690c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
691c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
692c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
693c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
694c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
695c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triX	= triNdx ? 1.0f-xf : xf;
696c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triY	= triNdx ? 1.0f-yf : yf;
697c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
698c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
699c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
700c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	r		= triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY);
701c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= triLod[triNdx];
702c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
703c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, s, t, r, lod) * params.colorScale + params.colorBias, x, y);
704c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
705c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
706c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
707c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
708c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture2DArrayView& src, const float* texCoord, const ReferenceParams& params)
709c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
710c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
711c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
712c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
713c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
714c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2012-02-17 pyry] Support projected lookups.
715c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTextureNonProjected(dst, src, sq, tq, rq, params);
716c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
717c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
718c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture1DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
719c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
720c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
721c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
722c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture1DArrayView				src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
723c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
724c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
725c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
726c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
727c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	deInt32										srcSize				= src.getWidth();
728c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
729c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
730c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
731c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
732c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										triLod[2]			= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias,
733c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																		computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias};
734c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
735c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
736c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
737c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int x = 0; x < dst.getWidth(); x++)
738c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
739c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
740c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
741c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
742c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
743c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triX	= triNdx ? 1.0f-xf : xf;
744c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triY	= triNdx ? 1.0f-yf : yf;
745c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
746c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
747c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
748c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= triLod[triNdx];
749c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
750c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, s, t, lod) * params.colorScale + params.colorBias, x, y);
751c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
752c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
753c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
754c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
755c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture1DArrayView& src, const float* texCoord, const ReferenceParams& params)
756c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
757c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
758c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
759c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
760c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(!(params.flags & ReferenceParams::PROJECTED)); // \todo [2014-06-09 mika] Support projected lookups.
761c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTextureNonProjected(dst, src, sq, tq, params);
762c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
763c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
764c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureNonProjected (const tcu::SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
765c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
766c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
767c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
768c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture3DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
769c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
770c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
771c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
772c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
773c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::IVec3									srcSize				= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
774c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
775c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
776c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
777c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
778c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
779c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias, params.minLod, params.maxLod),
780c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias, params.minLod, params.maxLod) };
781c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
782c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
783c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
784c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int x = 0; x < dst.getWidth(); x++)
785c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
786c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
787c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
788c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
789c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
790c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triX	= triNdx ? 1.0f-xf : xf;
791c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triY	= triNdx ? 1.0f-yf : yf;
792c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
793c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
794c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	t		= triangleInterpolate(triT[triNdx].x(), triT[triNdx].y(), triT[triNdx].z(), triX, triY);
795c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	r		= triangleInterpolate(triR[triNdx].x(), triR[triNdx].y(), triR[triNdx].z(), triX, triY);
796c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= triLod[triNdx];
797c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
798c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, x, y);
799c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
800c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
801c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
802c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
803c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureProjected (const tcu::SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
804c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
805c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
806c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
807c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture3DView					src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
808c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
809c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
810c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										dstW				= (float)dst.getWidth();
811c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float										dstH				= (float)dst.getHeight();
812c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
813c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4									uq					= sq * (float)src.getWidth();
814c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4									vq					= tq * (float)src.getHeight();
815c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4									wq					= rq * (float)src.getDepth();
816c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
817c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
818c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
819c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
820c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
821c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triV[2]				= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
822c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triW[2]				= { wq.swizzle(0, 1, 2), wq.swizzle(3, 2, 1) };
823c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triP[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
824c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
825c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < dst.getHeight(); py++)
826c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
827c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < dst.getWidth(); px++)
828c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
829c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	wx		= (float)px + 0.5f;
830c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	wy		= (float)py + 0.5f;
831c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	nx		= wx / dstW;
832c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	ny		= wy / dstH;
833c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
834c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
835c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triWx	= triNdx ? dstW - wx : wx;
836c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triWy	= triNdx ? dstH - wy : wy;
837c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triNx	= triNdx ? 1.0f - nx : nx;
838c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	triNy	= triNdx ? 1.0f - ny : ny;
839c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
840c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	s		= projectedTriInterpolate(triS[triNdx], triP[triNdx], triNx, triNy);
841c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	t		= projectedTriInterpolate(triT[triNdx], triP[triNdx], triNx, triNy);
842c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	r		= projectedTriInterpolate(triR[triNdx], triP[triNdx], triNx, triNy);
843c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			float	lod		= computeProjectedTriLod(params.lodMode, triU[triNdx], triV[triNdx], triW[triNdx], triP[triNdx], triWx, triWy, (float)dst.getWidth(), (float)dst.getHeight())
844c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							+ lodBias;
845c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
846c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(src.sample(params.sampler, s, t, r, lod) * params.colorScale + params.colorBias, px, py);
847c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
848c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
849c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
850c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
851c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::Texture3DView& src, const float* texCoord, const ReferenceParams& params)
852c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
853c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture3DView	view	= getSubView(src, params.baseLevel, params.maxLevel);
854c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				sq		= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
855c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
856c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4				rq		= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
857c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
858c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (params.flags & ReferenceParams::PROJECTED)
859c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		sampleTextureProjected(dst, view, sq, tq, rq, params);
860c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
861c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		sampleTextureNonProjected(dst, view, sq, tq, rq, params);
862c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
863c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
864c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic void sampleTextureCubeArray (const tcu::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)
865c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
866c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Separate combined DS formats
867c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
868c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::TextureCubeArrayView				src					= getEffectiveTextureView(rawSrc, srcLevelStorage, params.sampler);
869c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
870c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= (float)dst.getWidth();
871c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= (float)dst.getHeight();
872c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
873c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates per triangle.
874c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
875c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
876c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
877c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3									triQ[2]				= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
878c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
879c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
880c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
881c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
882c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < dst.getHeight(); py++)
883c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
884c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < dst.getWidth(); px++)
885c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
886c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		wx		= (float)px + 0.5f;
887c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		wy		= (float)py + 0.5f;
888c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		nx		= wx / dstW;
889c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		ny		= wy / dstH;
890c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
891c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
892c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		triNx	= triNdx ? 1.0f - nx : nx;
893c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		triNy	= triNdx ? 1.0f - ny : ny;
894c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
895c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec3	coord	(triangleInterpolate(triS[triNdx], triNx, triNy),
896c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket									 triangleInterpolate(triT[triNdx], triNx, triNy),
897c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket									 triangleInterpolate(triR[triNdx], triNx, triNy));
898c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
899c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		coordQ	= triangleInterpolate(triQ[triNdx], triNx, triNy);
900c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
901c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec3	coordDx	(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
902c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket									 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
903c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket									 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
904c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec3	coordDy	(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
905c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket									 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
906c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket									 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
907c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
908c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float		lod		= de::clamp(computeCubeLodFromDerivates(params.lodMode, coord, coordDx, coordDy, src.getSize()) + lodBias, params.minLod, params.maxLod);
909c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
910c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(execSample(src, params, coord.x(), coord.y(), coord.z(), coordQ, lod) * params.colorScale + params.colorBias, px, py);
911c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
912c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
913c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
914c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
915c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid sampleTexture (const tcu::SurfaceAccess& dst, const tcu::TextureCubeArrayView& src, const float* texCoord, const ReferenceParams& params)
916c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
917c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 sq = tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
918c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 tq = tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
919c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
920c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec4 qq = tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
921c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
922c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTextureCubeArray(dst, src, sq, tq, rq, qq, params);
923c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
924c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
925c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid fetchTexture (const tcu::SurfaceAccess& dst, const tcu::ConstPixelBufferAccess& src, const float* texCoord, const tcu::Vec4& colorScale, const tcu::Vec4& colorBias)
926c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
927c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		sq			= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
928c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
929c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
930c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
931c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
932c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int x = 0; x < dst.getWidth(); x++)
933c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
934c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float	yf		= ((float)y + 0.5f) / (float)dst.getHeight();
935c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float	xf		= ((float)x + 0.5f) / (float)dst.getWidth();
936c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
937c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const int	triNdx	= xf + yf >= 1.0f ? 1 : 0; // Top left fill rule.
938c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float	triX	= triNdx ? 1.0f-xf : xf;
939c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float	triY	= triNdx ? 1.0f-yf : yf;
940c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
941c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const float	s		= triangleInterpolate(triS[triNdx].x(), triS[triNdx].y(), triS[triNdx].z(), triX, triY);
942c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
943c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			dst.setPixel(src.getPixel((int)s, 0) * colorScale + colorBias, x, y);
944c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
945c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
946c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
947c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
948c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool compareImages (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold)
949c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
950c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::pixelThresholdCompare(log, "Result", "Image comparison result", reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
951c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
952c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
953c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool compareImages (tcu::TestLog& log, const char* name, const char* desc, const tcu::Surface& reference, const tcu::Surface& rendered, tcu::RGBA threshold)
954c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
955c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::pixelThresholdCompare(log, name, desc, reference, rendered, threshold, tcu::COMPARE_LOG_RESULT);
956c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
957c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
958c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint measureAccuracy (tcu::TestLog& log, const tcu::Surface& reference, const tcu::Surface& rendered, int bestScoreDiff, int worstScoreDiff)
959c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
960c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::measurePixelDiffAccuracy(log, "Result", "Image comparison result", reference, rendered, bestScoreDiff, worstScoreDiff, tcu::COMPARE_LOG_EVERYTHING);
961c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
962c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
963c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline int rangeDiff (int x, int a, int b)
964c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
965c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (x < a)
966c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return a-x;
967c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else if (x > b)
968c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return x-b;
969c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
970c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		return 0;
971c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
972c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
973c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline tcu::RGBA rangeDiff (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b)
974c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
975c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int rMin = de::min(a.getRed(),		b.getRed());
976c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int rMax = de::max(a.getRed(),		b.getRed());
977c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int gMin = de::min(a.getGreen(),	b.getGreen());
978c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int gMax = de::max(a.getGreen(),	b.getGreen());
979c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int bMin = de::min(a.getBlue(),		b.getBlue());
980c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int bMax = de::max(a.getBlue(),		b.getBlue());
981c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int aMin = de::min(a.getAlpha(),	b.getAlpha());
982c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int aMax = de::max(a.getAlpha(),	b.getAlpha());
983c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
984c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return tcu::RGBA(rangeDiff(p.getRed(),		rMin, rMax),
985c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					 rangeDiff(p.getGreen(),	gMin, gMax),
986c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					 rangeDiff(p.getBlue(),		bMin, bMax),
987c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					 rangeDiff(p.getAlpha(),	aMin, aMax));
988c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
989c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
990c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketinline bool rangeCompare (tcu::RGBA p, tcu::RGBA a, tcu::RGBA b, tcu::RGBA threshold)
991c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
992c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::RGBA diff = rangeDiff(p, a, b);
993c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return diff.getRed()	<= threshold.getRed() &&
994c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		   diff.getGreen()	<= threshold.getGreen() &&
995c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		   diff.getBlue()	<= threshold.getBlue() &&
996c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		   diff.getAlpha()	<= threshold.getAlpha();
997c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
998c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
999c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoord1D (std::vector<float>& dst, float left, float right)
1000c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1001c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(4);
1002c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1003c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0] = left;
1004c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[1] = left;
1005c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[2] = right;
1006c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[3] = right;
1007c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1008c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1009c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoord1DArray (std::vector<float>& dst, int layerNdx, float left, float right)
1010c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1011c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(4*2);
1012c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1013c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0] = left;	dst[1] = (float)layerNdx;
1014c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[2] = left;	dst[3] = (float)layerNdx;
1015c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[4] = right;	dst[5] = (float)layerNdx;
1016c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[6] = right;	dst[7] = (float)layerNdx;
1017c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1018c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1019c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoord2D (std::vector<float>& dst, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
1020c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1021c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(4*2);
1022c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1023c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0] = bottomLeft.x();	dst[1] = bottomLeft.y();
1024c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[2] = bottomLeft.x();	dst[3] = topRight.y();
1025c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[4] = topRight.x();		dst[5] = bottomLeft.y();
1026c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[6] = topRight.x();		dst[7] = topRight.y();
1027c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1028c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1029c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoord2DArray (std::vector<float>& dst, int layerNdx, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
1030c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1031c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(4*3);
1032c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1033c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0] = bottomLeft.x();	dst[ 1] = bottomLeft.y();	dst[ 2] = (float)layerNdx;
1034c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[3] = bottomLeft.x();	dst[ 4] = topRight.y();		dst[ 5] = (float)layerNdx;
1035c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[6] = topRight.x();		dst[ 7] = bottomLeft.y();	dst[ 8] = (float)layerNdx;
1036c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[9] = topRight.x();		dst[10] = topRight.y();		dst[11] = (float)layerNdx;
1037c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1038c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1039c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoord3D (std::vector<float>& dst, const tcu::Vec3& p0, const tcu::Vec3& p1, const tcu::IVec3& dirSwz)
1040c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1041c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 f0 = tcu::Vec3(0.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
1042c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 f1 = tcu::Vec3(0.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
1043c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 f2 = tcu::Vec3(1.0f, 0.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
1044c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 f3 = tcu::Vec3(1.0f, 1.0f, 0.0f).swizzle(dirSwz[0], dirSwz[1], dirSwz[2]);
1045c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1046c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 v0 = p0 + (p1-p0)*f0;
1047c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 v1 = p0 + (p1-p0)*f1;
1048c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 v2 = p0 + (p1-p0)*f2;
1049c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Vec3 v3 = p0 + (p1-p0)*f3;
1050c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1051c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(4*3);
1052c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1053c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0] = v0.x(); dst[ 1] = v0.y(); dst[ 2] = v0.z();
1054c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[3] = v1.x(); dst[ 4] = v1.y(); dst[ 5] = v1.z();
1055c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[6] = v2.x(); dst[ 7] = v2.y(); dst[ 8] = v2.z();
1056c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[9] = v3.x(); dst[10] = v3.y(); dst[11] = v3.z();
1057c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1058c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1059c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face)
1060c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1061c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	static const float texCoordNegX[] =
1062c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1063c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f,  1.0f, -1.0f,
1064c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, -1.0f, -1.0f,
1065c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f,  1.0f,  1.0f,
1066c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, -1.0f,  1.0f
1067c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1068c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	static const float texCoordPosX[] =
1069c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1070c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		+1.0f,  1.0f,  1.0f,
1071c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		+1.0f, -1.0f,  1.0f,
1072c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		+1.0f,  1.0f, -1.0f,
1073c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		+1.0f, -1.0f, -1.0f
1074c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1075c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	static const float texCoordNegY[] =
1076c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1077c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, -1.0f,  1.0f,
1078c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, -1.0f, -1.0f,
1079c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f, -1.0f,  1.0f,
1080c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f, -1.0f, -1.0f
1081c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1082c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	static const float texCoordPosY[] =
1083c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1084c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, +1.0f, -1.0f,
1085c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, +1.0f,  1.0f,
1086c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f, +1.0f, -1.0f,
1087c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f, +1.0f,  1.0f
1088c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1089c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	static const float texCoordNegZ[] =
1090c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1091c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f,  1.0f, -1.0f,
1092c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f, -1.0f, -1.0f,
1093c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f,  1.0f, -1.0f,
1094c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, -1.0f, -1.0f
1095c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1096c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	static const float texCoordPosZ[] =
1097c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1098c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f,  1.0f, +1.0f,
1099c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		-1.0f, -1.0f, +1.0f,
1100c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f,  1.0f, +1.0f,
1101c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		 1.0f, -1.0f, +1.0f
1102c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1103c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1104c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float*	texCoord		= DE_NULL;
1105c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				texCoordSize	= DE_LENGTH_OF_ARRAY(texCoordNegX);
1106c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1107c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (face)
1108c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1109c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_X: texCoord = texCoordNegX; break;
1110c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_X: texCoord = texCoordPosX; break;
1111c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Y: texCoord = texCoordNegY; break;
1112c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Y: texCoord = texCoordPosY; break;
1113c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Z: texCoord = texCoordNegZ; break;
1114c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Z: texCoord = texCoordPosZ; break;
1115c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
1116c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			DE_ASSERT(DE_FALSE);
1117c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return;
1118c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1119c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1120c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(texCoordSize);
1121c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::copy(texCoord, texCoord+texCoordSize, dst.begin());
1122c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1123c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1124c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
1125c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1126c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int		sRow		= 0;
1127c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int		tRow		= 0;
1128c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int		mRow		= 0;
1129c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float	sSign		= 1.0f;
1130c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float	tSign		= 1.0f;
1131c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float	mSign		= 1.0f;
1132c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1133c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (face)
1134c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1135c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;				   tSign = -1.0f;	break;
1136c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;				sSign = -1.0f; tSign = -1.0f;	break;
1137c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;				   tSign = -1.0f;	break;
1138c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;												break;
1139c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;	break;
1140c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;							   tSign = -1.0f;	break;
1141c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
1142c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			DE_ASSERT(DE_FALSE);
1143c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return;
1144c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1145c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1146c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(3*4);
1147c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1148c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0+mRow] = mSign;
1149c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[3+mRow] = mSign;
1150c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[6+mRow] = mSign;
1151c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[9+mRow] = mSign;
1152c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1153c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0+sRow] = sSign * bottomLeft.x();
1154c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[3+sRow] = sSign * bottomLeft.x();
1155c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[6+sRow] = sSign * topRight.x();
1156c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[9+sRow] = sSign * topRight.x();
1157c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1158c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[0+tRow] = tSign * bottomLeft.y();
1159c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[3+tRow] = tSign * topRight.y();
1160c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[6+tRow] = tSign * bottomLeft.y();
1161c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[9+tRow] = tSign * topRight.y();
1162c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1163c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1164c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketvoid computeQuadTexCoordCubeArray (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight, const tcu::Vec2& layerRange)
1165c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1166c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int			sRow	= 0;
1167c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int			tRow	= 0;
1168c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int			mRow	= 0;
1169c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int	qRow	= 3;
1170c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float		sSign	= 1.0f;
1171c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float		tSign	= 1.0f;
1172c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	float		mSign	= 1.0f;
1173c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float	l0		= layerRange.x();
1174c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float	l1		= layerRange.y();
1175c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1176c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	switch (face)
1177c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1178c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;				   tSign = -1.0f;	break;
1179c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;				sSign = -1.0f; tSign = -1.0f;	break;
1180c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;				   tSign = -1.0f;	break;
1181c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;												break;
1182c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;	break;
1183c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;							   tSign = -1.0f;	break;
1184c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		default:
1185c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			DE_ASSERT(DE_FALSE);
1186c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			return;
1187c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1188c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1189c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst.resize(4*4);
1190c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1191c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 0+mRow] = mSign;
1192c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 4+mRow] = mSign;
1193c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 8+mRow] = mSign;
1194c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[12+mRow] = mSign;
1195c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1196c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 0+sRow] = sSign * bottomLeft.x();
1197c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 4+sRow] = sSign * bottomLeft.x();
1198c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 8+sRow] = sSign * topRight.x();
1199c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[12+sRow] = sSign * topRight.x();
1200c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1201c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 0+tRow] = tSign * bottomLeft.y();
1202c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 4+tRow] = tSign * topRight.y();
1203c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[ 8+tRow] = tSign * bottomLeft.y();
1204c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	dst[12+tRow] = tSign * topRight.y();
1205c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1206c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (l0 != l1)
1207c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1208c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[ 0+qRow] = l0;
1209c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[ 4+qRow] = l0*0.5f + l1*0.5f;
1210c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[ 8+qRow] = l0*0.5f + l1*0.5f;
1211c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[12+qRow] = l1;
1212c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1213c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	else
1214c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1215c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[ 0+qRow] = l0;
1216c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[ 4+qRow] = l0;
1217c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[ 8+qRow] = l0;
1218c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		dst[12+qRow] = l0;
1219c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1220c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1221c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1222c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// Texture result verification
1223c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1224c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket//! Verifies texture lookup results and returns number of failed pixels.
1225c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
1226c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::ConstPixelBufferAccess&	reference,
1227c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::PixelBufferAccess&			errorMask,
1228c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::Texture1DView&				baseView,
1229c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const float*							texCoord,
1230c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const ReferenceParams&				sampleParams,
1231c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LookupPrecision&			lookupPrec,
1232c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LodPrecision&				lodPrec,
1233c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  qpWatchDog*							watchDog)
1234c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1235c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
1236c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
1237c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1238c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1239c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture1DView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
1240c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1241c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
1242c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1243c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
1244c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
1245c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
1246c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int									srcSize				= src.getWidth();
1247c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1248c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
1249c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
1250c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
1251c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1252c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
1253c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1254c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											numFailed			= 0;
1255c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1256c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
1257c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1258c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
1259c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
1260c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
1261c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
1262c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1263c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1264c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
1265c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1266c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
1267c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1268c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Ugly hack, validation can take way too long at the moment.
1269c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (watchDog)
1270c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			qpWatchDog_touch(watchDog);
1271c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1272c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
1273c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
1274c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
1275c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
1276c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1277c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try comparison to ideal reference first, and if that fails use slower verificator.
1278c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
1279c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
1280c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
1281c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
1282c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
1283c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
1284c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1285c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
1286c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWx	= triNdx ? dstW - wx : wx;
1287c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWy	= triNdx ? dstH - wy : wy;
1288c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNx	= triNdx ? 1.0f - nx : nx;
1289c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNy	= triNdx ? 1.0f - ny : ny;
1290c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1291c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		coord		= projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy);
1292c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		coordDx		= triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * float(srcSize);
1293c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		coordDy		= triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * float(srcSize);
1294c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1295c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec);
1296c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1297c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Compute lod bounds across lodOffsets range.
1298c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
1299c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1300c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
1301c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
1302c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nxo		= wxo/dstW;
1303c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nyo		= wyo/dstH;
1304c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1305c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float	coordDxo	= triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * float(srcSize);
1306c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float	coordDyo	= triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * float(srcSize);
1307c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	lodO	= tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec);
1308c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1309c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
1310c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
1311c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1312c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1313c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
1314c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
1315c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1316c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
1317c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1318c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
1319c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
1320c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1321c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
1322c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
1323c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1324c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1325c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
1326c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1327c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1328c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
1329c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::ConstPixelBufferAccess&	reference,
1330c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::PixelBufferAccess&			errorMask,
1331c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::Texture2DView&				baseView,
1332c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const float*							texCoord,
1333c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const ReferenceParams&				sampleParams,
1334c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LookupPrecision&			lookupPrec,
1335c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LodPrecision&				lodPrec,
1336c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  qpWatchDog*							watchDog)
1337c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1338c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
1339c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
1340c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1341c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1342c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture2DView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
1343c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1344c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
1345c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
1346c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1347c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
1348c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
1349c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
1350c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
1351c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1352c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
1353c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
1354c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
1355c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
1356c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1357c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
1358c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1359dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita	const float									posEps				= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
1360dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita
1361c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											numFailed			= 0;
1362c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1363c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
1364c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1365c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
1366c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
1367c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
1368c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
1369c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1370c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1371c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
1372c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1373c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
1374c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1375c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Ugly hack, validation can take way too long at the moment.
1376c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (watchDog)
1377c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			qpWatchDog_touch(watchDog);
1378c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1379c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
1380c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
1381c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
1382c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
1383c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1384c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try comparison to ideal reference first, and if that fails use slower verificator.
1385c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
1386c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
1387c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
1388c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
1389c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
1390c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
1391c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1392dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita				const bool		tri0	= (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f;
1393dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita				const bool		tri1	= (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f;
1394c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1395dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita				bool			isOk	= false;
1396c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1397dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita				DE_ASSERT(tri0 || tri1);
1398c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1399dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita				// Pixel can belong to either of the triangles if it lies close enough to the edge.
1400dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
1401c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1402dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const float		triWx	= triNdx ? dstW - wx : wx;
1403dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const float		triWy	= triNdx ? dstH - wy : wy;
1404dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const float		triNx	= triNdx ? 1.0f - nx : nx;
1405dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const float		triNy	= triNdx ? 1.0f - ny : ny;
1406dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita
1407dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const tcu::Vec2	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
1408dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
1409dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
1410dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita															triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
1411dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
1412dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita															triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
1413dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita
1414dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
1415dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita
1416dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					// Compute lod bounds across lodOffsets range.
1417dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
1418dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					{
1419dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
1420dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
1421dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						const float		nxo		= wxo/dstW;
1422dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						const float		nyo		= wyo/dstH;
1423dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita
1424dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
1425dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita																triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
1426dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
1427dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita																triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
1428dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
1429dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita
1430dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
1431dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
1432dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					}
1433dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita
1434dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
1435dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix))
1436dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					{
1437dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						isOk = true;
1438dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita						break;
1439dcb5991811ed287fc4a72126663136a94eb7dc39Kalle Raita					}
1440c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1441c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1442c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
1443c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1444c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
1445c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
1446c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1447c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
1448c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
1449c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1450c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1451c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
1452c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1453c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1454c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool verifyTextureResult (tcu::TestContext&						testCtx,
1455c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::ConstPixelBufferAccess&	result,
1456c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::Texture1DView&				src,
1457c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const float*							texCoord,
1458c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const ReferenceParams&				sampleParams,
1459c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LookupPrecision&			lookupPrec,
1460c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LodPrecision&				lodPrec,
1461c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::PixelFormat&				pixelFormat)
1462c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1463c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::TestLog&	log				= testCtx.getLog();
1464c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	reference		(result.getWidth(), result.getHeight());
1465c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
1466c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailedPixels;
1467c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1468c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
1469c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1470c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
1471c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
1472c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1473c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1474c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1475c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1476c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1477c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		<< tcu::TestLog::Image("Rendered", "Rendered image", result);
1478c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1479c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1480c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1481c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1482c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1483c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1484c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1485c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::EndImageSet;
1486c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1487c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailedPixels == 0;
1488c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1489c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1490c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool verifyTextureResult (tcu::TestContext&						testCtx,
1491c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::ConstPixelBufferAccess&	result,
1492c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::Texture2DView&				src,
1493c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const float*							texCoord,
1494c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const ReferenceParams&				sampleParams,
1495c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LookupPrecision&			lookupPrec,
1496c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LodPrecision&				lodPrec,
1497c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::PixelFormat&				pixelFormat)
1498c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1499c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::TestLog&	log				= testCtx.getLog();
1500c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	reference		(result.getWidth(), result.getHeight());
1501c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
1502c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailedPixels;
1503c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1504c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
1505c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1506c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
1507c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
1508c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1509c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1510c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1511c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1512c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1513c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		<< tcu::TestLog::Image("Rendered", "Rendered image", result);
1514c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1515c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1516c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1517c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1518c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1519c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1520c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1521c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::EndImageSet;
1522c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1523c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailedPixels == 0;
1524c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1525c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1526c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket//! Verifies texture lookup results and returns number of failed pixels.
1527c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
1528c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::ConstPixelBufferAccess&	reference,
1529c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::PixelBufferAccess&			errorMask,
1530c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::TextureCubeView&			baseView,
1531c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const float*							texCoord,
1532c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const ReferenceParams&				sampleParams,
1533c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LookupPrecision&			lookupPrec,
1534c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LodPrecision&				lodPrec,
1535c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  qpWatchDog*							watchDog)
1536c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1537c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
1538c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
1539c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1540c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1541c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::TextureCubeView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
1542c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1543c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
1544c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
1545c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
1546c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1547c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
1548c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
1549c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
1550c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int									srcSize				= src.getSize();
1551c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1552c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates per triangle.
1553c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
1554c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
1555c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
1556c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
1557c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1558c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
1559c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1560c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									posEps				= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
1561c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1562c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											numFailed			= 0;
1563c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1564c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
1565c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1566c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
1567c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
1568c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
1569c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
1570c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1571c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// \note Not strictly allowed by spec, but implementations do this in practice.
1572c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1, -1),
1573c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1, +1),
1574c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1, -1),
1575c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1, +1),
1576c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1577c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1578c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
1579c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1580c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
1581c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1582c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Ugly hack, validation can take way too long at the moment.
1583c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (watchDog)
1584c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			qpWatchDog_touch(watchDog);
1585c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1586c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
1587c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
1588c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
1589c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
1590c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1591c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try comparison to ideal reference first, and if that fails use slower verificator.
1592c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
1593c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
1594c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
1595c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
1596c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
1597c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
1598c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1599c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		tri0	= (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f;
1600c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		tri1	= (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f;
1601c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1602c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				bool			isOk	= false;
1603c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1604c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				DE_ASSERT(tri0 || tri1);
1605c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1606c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Pixel can belong to either of the triangles if it lies close enough to the edge.
1607c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
1608c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1609c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triWx	= triNdx ? dstW - wx : wx;
1610c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triWy	= triNdx ? dstH - wy : wy;
1611c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triNx	= triNdx ? 1.0f - nx : nx;
1612c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triNy	= triNdx ? 1.0f - ny : ny;
1613c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1614c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
1615c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
1616c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
1617c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
1618c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
1619c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
1620c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
1621c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
1622c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
1623c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1624c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
1625c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1626c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					// Compute lod bounds across lodOffsets range.
1627c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
1628c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					{
1629c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
1630c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
1631c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		nxo		= wxo/dstW;
1632c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		nyo		= wyo/dstH;
1633c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1634c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
1635c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
1636c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
1637c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
1638c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
1639c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
1640c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
1641c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
1642c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
1643c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
1644c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1645c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
1646c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
1647c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					}
1648c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1649c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
1650c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1651c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix))
1652c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					{
1653c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						isOk = true;
1654c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						break;
1655c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					}
1656c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1657c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1658c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
1659c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1660c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
1661c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
1662c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1663c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
1664c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
1665c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1666c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1667c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
1668c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1669c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1670c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool verifyTextureResult (tcu::TestContext&						testCtx,
1671c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::ConstPixelBufferAccess&	result,
1672c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::TextureCubeView&			src,
1673c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const float*							texCoord,
1674c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const ReferenceParams&				sampleParams,
1675c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LookupPrecision&			lookupPrec,
1676c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LodPrecision&				lodPrec,
1677c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::PixelFormat&				pixelFormat)
1678c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1679c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::TestLog&	log				= testCtx.getLog();
1680c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	reference		(result.getWidth(), result.getHeight());
1681c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
1682c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailedPixels;
1683c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1684c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
1685c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1686c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
1687c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
1688c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1689c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1690c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1691c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1692c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1693c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		<< tcu::TestLog::Image("Rendered", "Rendered image", result);
1694c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1695c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1696c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1697c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1698c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1699c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1700c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1701c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::EndImageSet;
1702c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1703c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailedPixels == 0;
1704c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1705c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1706c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket//! Verifies texture lookup results and returns number of failed pixels.
1707c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
1708c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::ConstPixelBufferAccess&	reference,
1709c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::PixelBufferAccess&			errorMask,
1710c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::Texture3DView&				baseView,
1711c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const float*							texCoord,
1712c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const ReferenceParams&				sampleParams,
1713c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LookupPrecision&			lookupPrec,
1714c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LodPrecision&				lodPrec,
1715c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  qpWatchDog*							watchDog)
1716c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1717c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
1718c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
1719c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1720c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1721c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture3DView					src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
1722c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1723c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
1724c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
1725c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
1726c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1727c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
1728c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
1729c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
1730c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec3							srcSize				= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
1731c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1732c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
1733c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
1734c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
1735c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
1736c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
1737c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1738c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
1739c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1740c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									posEps				= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
1741c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1742c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											numFailed			= 0;
1743c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1744c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
1745c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1746c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
1747c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
1748c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
1749c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
1750c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1751c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1752c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
1753c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1754c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
1755c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1756c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Ugly hack, validation can take way too long at the moment.
1757c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (watchDog)
1758c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			qpWatchDog_touch(watchDog);
1759c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1760c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
1761c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
1762c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
1763c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
1764c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1765c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try comparison to ideal reference first, and if that fails use slower verificator.
1766c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
1767c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
1768c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
1769c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
1770c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
1771c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
1772c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1773c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		tri0	= (wx-posEps)/dstW + (wy-posEps)/dstH <= 1.0f;
1774c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		tri1	= (wx+posEps)/dstW + (wy+posEps)/dstH >= 1.0f;
1775c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1776c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				bool			isOk	= false;
1777c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1778c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				DE_ASSERT(tri0 || tri1);
1779c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1780c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Pixel can belong to either of the triangles if it lies close enough to the edge.
1781c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
1782c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1783c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triWx	= triNdx ? dstW - wx : wx;
1784c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triWy	= triNdx ? dstH - wy : wy;
1785c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triNx	= triNdx ? 1.0f - nx : nx;
1786c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triNy	= triNdx ? 1.0f - ny : ny;
1787c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1788c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
1789c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
1790c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
1791c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDx		= tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
1792c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
1793c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
1794c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDy		= tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
1795c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
1796c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
1797c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1798c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDx.z(), coordDy.x(), coordDy.y(), coordDy.z(), lodPrec);
1799c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1800c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					// Compute lod bounds across lodOffsets range.
1801c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
1802c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					{
1803c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
1804c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
1805c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		nxo		= wxo/dstW;
1806c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		nyo		= wyo/dstH;
1807c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1808c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordDxo	= tcu::Vec3(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
1809c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
1810c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
1811c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordDyo	= tcu::Vec3(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
1812c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
1813c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
1814c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDxo.z(), coordDyo.x(), coordDyo.y(), coordDyo.z(), lodPrec);
1815c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1816c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
1817c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
1818c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					}
1819c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1820c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
1821c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1822c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix))
1823c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					{
1824c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						isOk = true;
1825c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						break;
1826c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					}
1827c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1828c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1829c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
1830c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1831c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
1832c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
1833c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1834c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
1835c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
1836c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1837c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1838c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
1839c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1840c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1841c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool verifyTextureResult (tcu::TestContext&						testCtx,
1842c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::ConstPixelBufferAccess&	result,
1843c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::Texture3DView&				src,
1844c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const float*							texCoord,
1845c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const ReferenceParams&				sampleParams,
1846c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LookupPrecision&			lookupPrec,
1847c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LodPrecision&				lodPrec,
1848c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::PixelFormat&				pixelFormat)
1849c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1850c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::TestLog&	log				= testCtx.getLog();
1851c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	reference		(result.getWidth(), result.getHeight());
1852c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
1853c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailedPixels;
1854c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1855c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
1856c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1857c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
1858c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
1859c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1860c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1861c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1862c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1863c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1864c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		<< tcu::TestLog::Image("Rendered", "Rendered image", result);
1865c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1866c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
1867c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1868c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1869c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1870c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1871c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1872c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::EndImageSet;
1873c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1874c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailedPixels == 0;
1875c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1876c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1877c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket//! Verifies texture lookup results and returns number of failed pixels.
1878c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
1879c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::ConstPixelBufferAccess&	reference,
1880c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::PixelBufferAccess&			errorMask,
1881c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::Texture1DArrayView&		baseView,
1882c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const float*							texCoord,
1883c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const ReferenceParams&				sampleParams,
1884c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LookupPrecision&			lookupPrec,
1885c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LodPrecision&				lodPrec,
1886c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  qpWatchDog*							watchDog)
1887c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1888c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
1889c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
1890c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1891c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1892c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture1DArrayView				src					= getEffectiveTextureView(baseView, srcLevelStorage, sampleParams.sampler);
1893c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1894c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
1895c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
1896c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1897c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
1898c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
1899c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
1900c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									srcSize				= float(src.getWidth()); // For lod computation, thus #layers is ignored.
1901c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1902c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
1903c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
1904c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
1905c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
1906c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1907c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
1908c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1909c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											numFailed			= 0;
1910c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1911c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
1912c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1913c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
1914c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
1915c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
1916c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
1917c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
1918c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1919c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
1920c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1921c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
1922c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
1923c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Ugly hack, validation can take way too long at the moment.
1924c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (watchDog)
1925c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			qpWatchDog_touch(watchDog);
1926c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1927c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
1928c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
1929c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
1930c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
1931c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1932c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try comparison to ideal reference first, and if that fails use slower verificator.
1933c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
1934c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
1935c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
1936c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
1937c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
1938c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
1939c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1940c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
1941c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWx	= triNdx ? dstW - wx : wx;
1942c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWy	= triNdx ? dstH - wy : wy;
1943c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNx	= triNdx ? 1.0f - nx : nx;
1944c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNy	= triNdx ? 1.0f - ny : ny;
1945c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1946c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coord	(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
1947c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
1948c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float	coordDx		= triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy) * srcSize;
1949c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float	coordDy		= triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx) * srcSize;
1950c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1951c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx, coordDy, lodPrec);
1952c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1953c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Compute lod bounds across lodOffsets range.
1954c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
1955c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1956c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
1957c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
1958c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nxo		= wxo/dstW;
1959c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nyo		= wyo/dstH;
1960c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1961c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float	coordDxo		= triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo) * srcSize;
1962c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float	coordDyo		= triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo) * srcSize;
1963c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo, coordDyo, lodPrec);
1964c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1965c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
1966c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
1967c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1968c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1969c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
1970c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
1971c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1972c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
1973c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
1974c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
1975c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
1976c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
1977c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
1978c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
1979c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
1980c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1981c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
1982c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
1983c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1984c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket//! Verifies texture lookup results and returns number of failed pixels.
1985c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
1986c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::ConstPixelBufferAccess&	reference,
1987c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::PixelBufferAccess&			errorMask,
1988c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::Texture2DArrayView&		baseView,
1989c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const float*							texCoord,
1990c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const ReferenceParams&				sampleParams,
1991c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LookupPrecision&			lookupPrec,
1992c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LodPrecision&				lodPrec,
1993c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  qpWatchDog*							watchDog)
1994c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
1995c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
1996c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
1997c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
1998c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1999c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Texture2DArrayView				src					= getEffectiveTextureView(baseView, srcLevelStorage, sampleParams.sampler);
2000c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2001c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
2002c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
2003c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
2004c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2005c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
2006c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
2007c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
2008c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								srcSize				= tcu::IVec2(src.getWidth(), src.getHeight()).asFloat(); // For lod computation, thus #layers is ignored.
2009c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2010c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
2011c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
2012c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
2013c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
2014c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
2015c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2016c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
2017c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2018c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											numFailed			= 0;
2019c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2020c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
2021c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2022c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
2023c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
2024c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
2025c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
2026c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
2027c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2028c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
2029c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2030c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
2031c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2032c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Ugly hack, validation can take way too long at the moment.
2033c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (watchDog)
2034c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			qpWatchDog_touch(watchDog);
2035c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2036c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
2037c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2038c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
2039c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
2040c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2041c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try comparison to ideal reference first, and if that fails use slower verificator.
2042c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
2043c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2044c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
2045c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
2046c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
2047c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
2048c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2049c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
2050c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWx	= triNdx ? dstW - wx : wx;
2051c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWy	= triNdx ? dstH - wy : wy;
2052c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNx	= triNdx ? 1.0f - nx : nx;
2053c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNy	= triNdx ? 1.0f - ny : ny;
2054c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2055c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
2056c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
2057c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
2058c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
2059c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize;
2060c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
2061c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize;
2062c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2063c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
2064c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2065c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Compute lod bounds across lodOffsets range.
2066c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
2067c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2068c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
2069c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
2070c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nxo		= wxo/dstW;
2071c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nyo		= wyo/dstH;
2072c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2073c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
2074c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize;
2075c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
2076c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize;
2077c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
2078c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2079c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
2080c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
2081c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2082c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2083c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
2084c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		isOk		= tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coord, clampedLod, resPix);
2085c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2086c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
2087c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2088c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2089c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
2090c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2091c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2092c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2093c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2094c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2095c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2096c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2097c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2098c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool verifyTextureResult (tcu::TestContext&						testCtx,
2099c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::ConstPixelBufferAccess&	result,
2100c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::Texture1DArrayView&		src,
2101c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const float*							texCoord,
2102c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const ReferenceParams&				sampleParams,
2103c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LookupPrecision&			lookupPrec,
2104c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LodPrecision&				lodPrec,
2105c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::PixelFormat&				pixelFormat)
2106c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2107c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::TestLog&	log				= testCtx.getLog();
2108c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	reference		(result.getWidth(), result.getHeight());
2109c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
2110c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailedPixels;
2111c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2112c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
2113c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2114c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
2115c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
2116c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2117c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
2118c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
2119c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2120c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
2121c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		<< tcu::TestLog::Image("Rendered", "Rendered image", result);
2122c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2123c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
2124c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2125c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
2126c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
2127c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2128c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2129c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::EndImageSet;
2130c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2131c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailedPixels == 0;
2132c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2133c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2134c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool verifyTextureResult (tcu::TestContext&						testCtx,
2135c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::ConstPixelBufferAccess&	result,
2136c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::Texture2DArrayView&		src,
2137c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const float*							texCoord,
2138c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const ReferenceParams&				sampleParams,
2139c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LookupPrecision&			lookupPrec,
2140c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LodPrecision&				lodPrec,
2141c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::PixelFormat&				pixelFormat)
2142c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2143c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::TestLog&	log				= testCtx.getLog();
2144c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	reference		(result.getWidth(), result.getHeight());
2145c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
2146c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailedPixels;
2147c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2148c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
2149c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2150c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
2151c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, lodPrec, testCtx.getWatchDog());
2152c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2153c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
2154c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
2155c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2156c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
2157c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		<< tcu::TestLog::Image("Rendered", "Rendered image", result);
2158c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2159c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
2160c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2161c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
2162c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
2163c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2164c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2165c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::EndImageSet;
2166c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2167c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailedPixels == 0;
2168c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2169c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2170c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket//! Verifies texture lookup results and returns number of failed pixels.
2171c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
2172c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::ConstPixelBufferAccess&	reference,
2173c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::PixelBufferAccess&			errorMask,
2174c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::TextureCubeArrayView&		baseView,
2175c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const float*							texCoord,
2176c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const ReferenceParams&				sampleParams,
2177c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LookupPrecision&			lookupPrec,
2178c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::IVec4&						coordBits,
2179c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  const tcu::LodPrecision&				lodPrec,
2180c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							  qpWatchDog*							watchDog)
2181c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2182c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
2183c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
2184c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2185c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
2186c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::TextureCubeArrayView				src					= getEffectiveTextureView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
2187c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2188c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
2189c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
2190c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
2191c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4								qq					= tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
2192c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2193c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
2194c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstW				= float(dstSize.x());
2195c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									dstH				= float(dstSize.y());
2196c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int									srcSize				= src.getSize();
2197c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2198c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates per triangle.
2199c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
2200c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
2201c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
2202c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triQ[2]				= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
2203c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
2204c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2205c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
2206c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2207c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float									posEps				= 1.0f / float((1<<4) + 1); // ES3 requires at least 4 subpixel bits.
2208c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2209c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int											numFailed			= 0;
2210c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2211c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
2212c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2213c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
2214c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
2215c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
2216c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
2217c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2218c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// \note Not strictly allowed by spec, but implementations do this in practice.
2219c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1, -1),
2220c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1, +1),
2221c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1, -1),
2222c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1, +1),
2223c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
2224c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2225c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
2226c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2227c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
2228c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2229c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Ugly hack, validation can take way too long at the moment.
2230c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (watchDog)
2231c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			qpWatchDog_touch(watchDog);
2232c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2233c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
2234c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2235c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= (result.getPixel(px, py)		- sampleParams.colorBias) / sampleParams.colorScale;
2236c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= (reference.getPixel(px, py)	- sampleParams.colorBias) / sampleParams.colorScale;
2237c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2238c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try comparison to ideal reference first, and if that fails use slower verificator.
2239c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(resPix - refPix), lookupPrec.colorThreshold)))
2240c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2241c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
2242c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
2243c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
2244c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
2245c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2246c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		tri0	= nx + ny - posEps <= 1.0f;
2247c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		tri1	= nx + ny + posEps >= 1.0f;
2248c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2249c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				bool			isOk	= false;
2250c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2251c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				DE_ASSERT(tri0 || tri1);
2252c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2253c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Pixel can belong to either of the triangles if it lies close enough to the edge.
2254c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int triNdx = (tri0?0:1); triNdx <= (tri1?1:0); triNdx++)
2255c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2256c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triWx		= triNdx ? dstW - wx : wx;
2257c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triWy		= triNdx ? dstH - wy : wy;
2258c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triNx		= triNdx ? 1.0f - nx : nx;
2259c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		triNy		= triNdx ? 1.0f - ny : ny;
2260c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2261c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec4	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
2262c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
2263c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy),
2264c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triQ[triNdx], triW[triNdx], triNx, triNy));
2265c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
2266c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
2267c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
2268c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
2269c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
2270c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
2271c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2272c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord.toWidth<3>(), coordDx, coordDy, srcSize, lodPrec);
2273c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2274c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					// Compute lod bounds across lodOffsets range.
2275c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
2276c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					{
2277c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		wxo			= triWx + lodOffsets[lodOffsNdx].x();
2278c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		wyo			= triWy + lodOffsets[lodOffsNdx].y();
2279c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		nxo			= wxo/dstW;
2280c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const float		nyo			= wyo/dstH;
2281c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2282c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
2283c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
2284c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
2285c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
2286c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
2287c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
2288c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
2289c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
2290c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket													 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
2291c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
2292c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2293c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						lodBounds.x() = de::min(lodBounds.x(), lodO.x());
2294c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						lodBounds.y() = de::max(lodBounds.y(), lodO.y());
2295c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					}
2296c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2297c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
2298c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2299c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					if (tcu::isLookupResultValid(src, sampleParams.sampler, lookupPrec, coordBits, coord, clampedLod, resPix))
2300c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					{
2301c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						isOk = true;
2302c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						break;
2303c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					}
2304c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2305c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2306c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
2307c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2308c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2309c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
2310c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2311c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2312c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2313c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2314c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2315c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2316c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2317c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2318c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketbool verifyTextureResult (tcu::TestContext&						testCtx,
2319c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::ConstPixelBufferAccess&	result,
2320c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::TextureCubeArrayView&		src,
2321c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const float*							texCoord,
2322c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const ReferenceParams&				sampleParams,
2323c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LookupPrecision&			lookupPrec,
2324c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::IVec4&						coordBits,
2325c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::LodPrecision&				lodPrec,
2326c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket						  const tcu::PixelFormat&				pixelFormat)
2327c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2328c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::TestLog&	log				= testCtx.getLog();
2329c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	reference		(result.getWidth(), result.getHeight());
2330c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::Surface	errorMask		(result.getWidth(), result.getHeight());
2331c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailedPixels;
2332c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2333c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(getCompareMask(pixelFormat) == lookupPrec.colorMask);
2334c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2335c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
2336c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	numFailedPixels = computeTextureLookupDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, lookupPrec, coordBits, lodPrec, testCtx.getWatchDog());
2337c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2338c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
2339c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
2340c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2341c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
2342c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		<< tcu::TestLog::Image("Rendered", "Rendered image", result);
2343c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2344c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	if (numFailedPixels > 0)
2345c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2346c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
2347c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
2348c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2349c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2350c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	log << tcu::TestLog::EndImageSet;
2351c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2352c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailedPixels == 0;
2353c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2354c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2355c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// Shadow lookup verification
2356c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2357c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
2358c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::ConstPixelBufferAccess&	reference,
2359c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::PixelBufferAccess&		errorMask,
2360c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::Texture2DView&			src,
2361c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const float*							texCoord,
2362c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const ReferenceParams&				sampleParams,
2363c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::TexComparePrecision&		comparePrec,
2364c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::LodPrecision&				lodPrec,
2365c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::Vec3&						nonShadowThreshold)
2366c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2367c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
2368c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
2369c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2370c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
2371c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
2372c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2373c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
2374c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float			dstW			= float(dstSize.x());
2375c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float			dstH			= float(dstSize.y());
2376c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
2377c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2378c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
2379c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
2380c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
2381c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
2382c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2383c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
2384c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2385c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int					numFailed		= 0;
2386c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2387c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
2388c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2389c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
2390c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
2391c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
2392c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
2393c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
2394c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2395c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
2396c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2397c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
2398c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2399c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
2400c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2401c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= result.getPixel(px, py);
2402c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= reference.getPixel(px, py);
2403c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2404c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Other channels should trivially match to reference.
2405c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
2406c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2407c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2408c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				numFailed += 1;
2409c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				continue;
2410c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2411c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2412c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Reference result is known to be a valid result, we can
2413c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// skip verification if thes results are equal
2414c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (resPix.x() != refPix.x())
2415c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2416c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
2417c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
2418c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
2419c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
2420c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2421c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
2422c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWx	= triNdx ? dstW - wx : wx;
2423c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWy	= triNdx ? dstH - wy : wy;
2424c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNx	= triNdx ? 1.0f - nx : nx;
2425c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNy	= triNdx ? 1.0f - ny : ny;
2426c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2427c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
2428c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy));
2429c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
2430c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
2431c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
2432c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
2433c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2434c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
2435c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2436c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Compute lod bounds across lodOffsets range.
2437c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
2438c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2439c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
2440c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
2441c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nxo		= wxo/dstW;
2442c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nyo		= wyo/dstH;
2443c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2444c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
2445c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
2446c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
2447c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
2448c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
2449c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2450c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
2451c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
2452c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2453c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2454c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
2455c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
2456c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2457c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
2458c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2459c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2460c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
2461c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2462c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2463c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2464c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2465c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2466c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2467c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2468c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2469c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
2470c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::ConstPixelBufferAccess&	reference,
2471c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::PixelBufferAccess&		errorMask,
2472c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::TextureCubeView&			src,
2473c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const float*							texCoord,
2474c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const ReferenceParams&				sampleParams,
2475c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::TexComparePrecision&		comparePrec,
2476c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::LodPrecision&				lodPrec,
2477c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::Vec3&						nonShadowThreshold)
2478c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2479c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
2480c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
2481c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2482c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
2483c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
2484c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
2485c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2486c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
2487c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float			dstW			= float(dstSize.x());
2488c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float			dstH			= float(dstSize.y());
2489c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const int			srcSize			= src.getSize();
2490c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2491c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates per triangle.
2492c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
2493c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
2494c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
2495c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
2496c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2497c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
2498c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2499c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int					numFailed		= 0;
2500c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2501c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
2502c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2503c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
2504c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
2505c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
2506c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
2507c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
2508c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2509c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
2510c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2511c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
2512c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2513c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
2514c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2515c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= result.getPixel(px, py);
2516c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= reference.getPixel(px, py);
2517c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2518c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Other channels should trivially match to reference.
2519c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
2520c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2521c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2522c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				numFailed += 1;
2523c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				continue;
2524c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2525c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2526c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Reference result is known to be a valid result, we can
2527c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// skip verification if thes results are equal
2528c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (resPix.x() != refPix.x())
2529c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2530c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
2531c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
2532c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
2533c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
2534c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2535c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
2536c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWx	= triNdx ? dstW - wx : wx;
2537c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWy	= triNdx ? dstH - wy : wy;
2538c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNx	= triNdx ? 1.0f - nx : nx;
2539c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNy	= triNdx ? 1.0f - ny : ny;
2540c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2541c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
2542c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
2543c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
2544c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec3	coordDx		(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
2545c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy),
2546c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 triDerivateX(triR[triNdx], triW[triNdx], wx, dstW, triNy));
2547c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec3	coordDy		(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
2548c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx),
2549c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 triDerivateY(triR[triNdx], triW[triNdx], wy, dstH, triNx));
2550c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2551c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				tcu::Vec2		lodBounds	= tcu::computeCubeLodBoundsFromDerivates(coord, coordDx, coordDy, srcSize, lodPrec);
2552c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2553c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Compute lod bounds across lodOffsets range.
2554c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
2555c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2556c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
2557c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
2558c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nxo		= wxo/dstW;
2559c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nyo		= wyo/dstH;
2560c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2561c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordO		(projectedTriInterpolate(triS[triNdx], triW[triNdx], nxo, nyo),
2562c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triT[triNdx], triW[triNdx], nxo, nyo),
2563c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 projectedTriInterpolate(triR[triNdx], triW[triNdx], nxo, nyo));
2564c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDxo	(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
2565c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo),
2566c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateX(triR[triNdx], triW[triNdx], wxo, dstW, nyo));
2567c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec3	coordDyo	(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
2568c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo),
2569c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket												 triDerivateY(triR[triNdx], triW[triNdx], wyo, dstH, nxo));
2570c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	lodO		= tcu::computeCubeLodBoundsFromDerivates(coordO, coordDxo, coordDyo, srcSize, lodPrec);
2571c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2572c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
2573c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
2574c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2575c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2576c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
2577c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
2578c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2579c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
2580c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2581c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2582c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
2583c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2584c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2585c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2586c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2587c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2588c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2589c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2590c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2591c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketint computeTextureCompareDiff (const tcu::ConstPixelBufferAccess&	result,
2592c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::ConstPixelBufferAccess&	reference,
2593c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::PixelBufferAccess&		errorMask,
2594c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::Texture2DArrayView&		src,
2595c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const float*							texCoord,
2596c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const ReferenceParams&				sampleParams,
2597c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::TexComparePrecision&		comparePrec,
2598c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::LodPrecision&				lodPrec,
2599c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket							   const tcu::Vec3&						nonShadowThreshold)
2600c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2601c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
2602c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
2603c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2604c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
2605c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
2606c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
2607c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2608c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
2609c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float			dstW			= float(dstSize.x());
2610c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float			dstH			= float(dstSize.y());
2611c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
2612c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2613c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Coordinates and lod per triangle.
2614c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
2615c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
2616c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
2617c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
2618c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2619c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
2620c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2621c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int					numFailed		= 0;
2622c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2623c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Vec2 lodOffsets[] =
2624c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2625c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(-1,  0),
2626c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2(+1,  0),
2627c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, -1),
2628c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec2( 0, +1),
2629c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	};
2630c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2631c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::clear(errorMask, tcu::RGBA::green().toVec());
2632c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2633c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int py = 0; py < result.getHeight(); py++)
2634c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2635c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int px = 0; px < result.getWidth(); px++)
2636c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2637c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	resPix	= result.getPixel(px, py);
2638c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::Vec4	refPix	= reference.getPixel(px, py);
2639c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2640c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Other channels should trivially match to reference.
2641c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!tcu::boolAll(tcu::lessThanEqual(tcu::abs(refPix.swizzle(1,2,3) - resPix.swizzle(1,2,3)), nonShadowThreshold)))
2642c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2643c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2644c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				numFailed += 1;
2645c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				continue;
2646c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2647c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2648c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Reference result is known to be a valid result, we can
2649c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// skip verification if thes results are equal
2650c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (resPix.x() != refPix.x())
2651c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2652c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wx		= (float)px + 0.5f;
2653c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		wy		= (float)py + 0.5f;
2654c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		nx		= wx / dstW;
2655c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		ny		= wy / dstH;
2656c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2657c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		triNdx	= nx + ny >= 1.0f ? 1 : 0;
2658c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWx	= triNdx ? dstW - wx : wx;
2659c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triWy	= triNdx ? dstH - wy : wy;
2660c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNx	= triNdx ? 1.0f - nx : nx;
2661c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const float		triNy	= triNdx ? 1.0f - ny : ny;
2662c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2663c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec3	coord		(projectedTriInterpolate(triS[triNdx], triW[triNdx], triNx, triNy),
2664c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 projectedTriInterpolate(triT[triNdx], triW[triNdx], triNx, triNy),
2665c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket											 projectedTriInterpolate(triR[triNdx], triW[triNdx], triNx, triNy));
2666c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coordDx		= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wx, dstW, triNy),
2667c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket														triDerivateX(triT[triNdx], triW[triNdx], wx, dstW, triNy)) * srcSize.asFloat();
2668c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	coordDy		= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wy, dstH, triNx),
2669c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket														triDerivateY(triT[triNdx], triW[triNdx], wy, dstH, triNx)) * srcSize.asFloat();
2670c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2671c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				tcu::Vec2		lodBounds	= tcu::computeLodBoundsFromDerivates(coordDx.x(), coordDx.y(), coordDy.x(), coordDy.y(), lodPrec);
2672c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2673c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				// Compute lod bounds across lodOffsets range.
2674c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				for (int lodOffsNdx = 0; lodOffsNdx < DE_LENGTH_OF_ARRAY(lodOffsets); lodOffsNdx++)
2675c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2676c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wxo		= triWx + lodOffsets[lodOffsNdx].x();
2677c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		wyo		= triWy + lodOffsets[lodOffsNdx].y();
2678c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nxo		= wxo/dstW;
2679c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const float		nyo		= wyo/dstH;
2680c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2681c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	coordDxo	= tcu::Vec2(triDerivateX(triS[triNdx], triW[triNdx], wxo, dstW, nyo),
2682c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateX(triT[triNdx], triW[triNdx], wxo, dstW, nyo)) * srcSize.asFloat();
2683c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	coordDyo	= tcu::Vec2(triDerivateY(triS[triNdx], triW[triNdx], wyo, dstH, nxo),
2684c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket															triDerivateY(triT[triNdx], triW[triNdx], wyo, dstH, nxo)) * srcSize.asFloat();
2685c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					const tcu::Vec2	lodO		= tcu::computeLodBoundsFromDerivates(coordDxo.x(), coordDxo.y(), coordDyo.x(), coordDyo.y(), lodPrec);
2686c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2687c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.x() = de::min(lodBounds.x(), lodO.x());
2688c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					lodBounds.y() = de::max(lodBounds.y(), lodO.y());
2689c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2690c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2691c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec2	clampedLod	= tcu::clampLodBounds(lodBounds + lodBias, tcu::Vec2(sampleParams.minLod, sampleParams.maxLod), lodPrec);
2692c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const bool		isOk		= tcu::isTexCompareResultValid(src, sampleParams.sampler, comparePrec, coord, clampedLod, sampleParams.ref, resPix.x());
2693c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2694c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (!isOk)
2695c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2696c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					errorMask.setPixel(tcu::RGBA::red().toVec(), px, py);
2697c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					numFailed += 1;
2698c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2699c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2700c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2701c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2702c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2703c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2704c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2705c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2706c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// Mipmap generation comparison.
2707c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2708c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic int compareGenMipmapBilinear (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
2709c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2710c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
2711c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2712c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		dstW		= float(dst.getWidth());
2713c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		dstH		= float(dst.getHeight());
2714c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		srcW		= float(src.getWidth());
2715c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		srcH		= float(src.getHeight());
2716c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailed	= 0;
2717c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2718c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Translation to lookup verification parameters.
2719c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
2720c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */);
2721c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::LookupPrecision	lookupPrec;
2722c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2723c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.colorThreshold	= precision.colorThreshold;
2724c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.colorMask		= precision.colorMask;
2725c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.coordBits		= tcu::IVec3(22);
2726c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.uvwBits			= precision.filterBits;
2727c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2728c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
2729c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int x = 0; x < dst.getWidth(); x++)
2730c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2731c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::Vec4	result	= dst.getPixel(x, y);
2732c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		cx		= (float(x)+0.5f) / dstW * srcW;
2733c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		cy		= (float(y)+0.5f) / dstH * srcH;
2734c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const bool		isOk	= tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result);
2735c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2736c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		errorMask.setPixel(isOk ? tcu::RGBA::green().toVec() : tcu::RGBA::red().toVec(), x, y);
2737c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!isOk)
2738c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			numFailed += 1;
2739c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2740c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2741c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2742c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2743c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2744c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic int compareGenMipmapBox (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
2745c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2746c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
2747c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2748c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		dstW		= float(dst.getWidth());
2749c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		dstH		= float(dst.getHeight());
2750c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		srcW		= float(src.getWidth());
2751c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		srcH		= float(src.getHeight());
2752c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailed	= 0;
2753c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2754c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Translation to lookup verification parameters.
2755c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const tcu::Sampler		sampler		(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
2756c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket										 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR, 0.0f, false /* non-normalized coords */);
2757c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	tcu::LookupPrecision	lookupPrec;
2758c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2759c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.colorThreshold	= precision.colorThreshold;
2760c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.colorMask		= precision.colorMask;
2761c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.coordBits		= tcu::IVec3(22);
2762c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	lookupPrec.uvwBits			= precision.filterBits;
2763c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2764c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
2765c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int x = 0; x < dst.getWidth(); x++)
2766c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2767c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::Vec4	result	= dst.getPixel(x, y);
2768c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		cx		= deFloatFloor(float(x) / dstW * srcW) + 1.0f;
2769c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const float		cy		= deFloatFloor(float(y) / dstH * srcH) + 1.0f;
2770c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const bool		isOk	= tcu::isLinearSampleResultValid(src, sampler, lookupPrec, tcu::Vec2(cx, cy), 0, result);
2771c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2772c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		errorMask.setPixel(isOk ? tcu::RGBA::green().toVec() : tcu::RGBA::red().toVec(), x, y);
2773c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!isOk)
2774c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			numFailed += 1;
2775c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2776c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2777c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2778c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2779c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2780c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstatic int compareGenMipmapVeryLenient (const tcu::ConstPixelBufferAccess& dst, const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& errorMask, const GenMipmapPrecision& precision)
2781c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2782c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_ASSERT(dst.getDepth() == 1 && src.getDepth() == 1); // \todo [2013-10-29 pyry] 3D textures.
2783c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_UNREF(precision);
2784c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2785c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		dstW		= float(dst.getWidth());
2786c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		dstH		= float(dst.getHeight());
2787c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		srcW		= float(src.getWidth());
2788c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	const float		srcH		= float(src.getHeight());
2789c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	int				numFailed	= 0;
2790c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2791c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int y = 0; y < dst.getHeight(); y++)
2792c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int x = 0; x < dst.getWidth(); x++)
2793c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2794c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::Vec4	result	= dst.getPixel(x, y);
2795c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const int		minX		= deFloorFloatToInt32(((float)x-0.5f) / dstW * srcW);
2796c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const int		minY		= deFloorFloatToInt32(((float)y-0.5f) / dstH * srcH);
2797c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const int		maxX		= deCeilFloatToInt32(((float)x+1.5f) / dstW * srcW);
2798c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const int		maxY		= deCeilFloatToInt32(((float)y+1.5f) / dstH * srcH);
2799c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Vec4		minVal, maxVal;
2800c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		bool			isOk;
2801c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2802c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		DE_ASSERT(minX < maxX && minY < maxY);
2803c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2804c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int ky = minY; ky <= maxY; ky++)
2805c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2806c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			for (int kx = minX; kx <= maxX; kx++)
2807c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2808c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		sx		= de::clamp(kx, 0, src.getWidth()-1);
2809c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int		sy		= de::clamp(ky, 0, src.getHeight()-1);
2810c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const tcu::Vec4	sample	= src.getPixel(sx, sy);
2811c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2812c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (ky == minY && kx == minX)
2813c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2814c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					minVal = sample;
2815c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					maxVal = sample;
2816c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2817c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				else
2818c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				{
2819c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					minVal = min(sample, minVal);
2820c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					maxVal = max(sample, maxVal);
2821c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				}
2822c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2823c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2824c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2825c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		isOk = boolAll(logicalAnd(lessThanEqual(minVal, result), lessThanEqual(result, maxVal)));
2826c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2827c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		errorMask.setPixel(isOk ? tcu::RGBA::green().toVec() : tcu::RGBA::red().toVec(), x, y);
2828c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!isOk)
2829c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			numFailed += 1;
2830c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2831c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2832c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return numFailed;
2833c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2834c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2835c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter SiketqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::Texture2D& resultTexture, const tcu::Texture2D& level0Reference, const GenMipmapPrecision& precision)
2836c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2837c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	qpTestResult result = QP_TEST_RESULT_PASS;
2838c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2839c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Special comparison for level 0.
2840c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2841c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::Vec4		threshold	= select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask);
2842c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const bool			level0Ok	= tcu::floatThresholdCompare(log, "Level0", "Level 0", level0Reference.getLevel(0), resultTexture.getLevel(0), threshold, tcu::COMPARE_LOG_RESULT);
2843c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2844c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!level0Ok)
2845c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2846c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			log << tcu::TestLog::Message << "ERROR: Level 0 comparison failed!" << tcu::TestLog::EndMessage;
2847c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			result = QP_TEST_RESULT_FAIL;
2848c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2849c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2850c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2851c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++)
2852c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2853c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::ConstPixelBufferAccess	src			= resultTexture.getLevel(levelNdx-1);
2854c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::ConstPixelBufferAccess	dst			= resultTexture.getLevel(levelNdx);
2855c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		tcu::Surface						errorMask	(dst.getWidth(), dst.getHeight());
2856c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		bool								levelOk		= false;
2857c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2858c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// Try different comparisons in quality order.
2859c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2860c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!levelOk)
2861c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2862c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision);
2863c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (numFailed == 0)
2864c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				levelOk = true;
2865c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			else
2866c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage;
2867c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2868c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2869c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!levelOk)
2870c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2871c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision);
2872c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (numFailed == 0)
2873c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				levelOk = true;
2874c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			else
2875c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << " comparison to box method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage;
2876c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2877c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2878c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		// At this point all high-quality methods have been used.
2879c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!levelOk && result == QP_TEST_RESULT_PASS)
2880c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			result = QP_TEST_RESULT_QUALITY_WARNING;
2881c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2882c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!levelOk)
2883c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2884c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision);
2885c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (numFailed == 0)
2886c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				levelOk = true;
2887c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			else
2888c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				log << tcu::TestLog::Message << "ERROR: Level " << levelNdx << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << tcu::TestLog::EndMessage;
2889c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2890c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2891c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!levelOk)
2892c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			result = QP_TEST_RESULT_FAIL;
2893c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2894c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::ImageSet(string("Level") + de::toString(levelNdx), string("Level ") + de::toString(levelNdx) + " result")
2895c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			<< tcu::TestLog::Image("Result", "Result", dst);
2896c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2897c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!levelOk)
2898c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			log << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
2899c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2900c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		log << tcu::TestLog::EndImageSet;
2901c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2902c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2903c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return result;
2904c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2905c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2906c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter SiketqpTestResult compareGenMipmapResult (tcu::TestLog& log, const tcu::TextureCube& resultTexture, const tcu::TextureCube& level0Reference, const GenMipmapPrecision& precision)
2907c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2908c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	qpTestResult result = QP_TEST_RESULT_PASS;
2909c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2910c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	static const char* s_faceNames[] = { "-X", "+X", "-Y", "+Y", "-Z", "+Z" };
2911c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_faceNames) == tcu::CUBEFACE_LAST);
2912c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2913c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	// Special comparison for level 0.
2914c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
2915c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2916c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::CubeFace	face		= tcu::CubeFace(faceNdx);
2917c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const tcu::Vec4		threshold	= select(precision.colorThreshold, tcu::Vec4(1.0f), precision.colorMask);
2918c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		const bool			level0Ok	= tcu::floatThresholdCompare(log,
2919c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																	 ("Level0Face" + de::toString(faceNdx)).c_str(),
2920c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																	 (string("Level 0, face ") + s_faceNames[face]).c_str(),
2921c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																	 level0Reference.getLevelFace(0, face),
2922c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																	 resultTexture.getLevelFace(0, face),
2923c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket																	 threshold, tcu::COMPARE_LOG_RESULT);
2924c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2925c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		if (!level0Ok)
2926c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2927c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			log << tcu::TestLog::Message << "ERROR: Level 0, face " << s_faceNames[face] << " comparison failed!" << tcu::TestLog::EndMessage;
2928c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			result = QP_TEST_RESULT_FAIL;
2929c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2930c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2931c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2932c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	for (int levelNdx = 1; levelNdx < resultTexture.getNumLevels(); levelNdx++)
2933c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	{
2934c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
2935c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		{
2936c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::CubeFace					face		= tcu::CubeFace(faceNdx);
2937c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const char*							faceName	= s_faceNames[face];
2938c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::ConstPixelBufferAccess	src			= resultTexture.getLevelFace(levelNdx-1,	face);
2939c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			const tcu::ConstPixelBufferAccess	dst			= resultTexture.getLevelFace(levelNdx,		face);
2940c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			tcu::Surface						errorMask	(dst.getWidth(), dst.getHeight());
2941c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			bool								levelOk		= false;
2942c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2943c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// Try different comparisons in quality order.
2944c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2945c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!levelOk)
2946c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2947c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int numFailed = compareGenMipmapBilinear(dst, src, errorMask.getAccess(), precision);
2948c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (numFailed == 0)
2949c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					levelOk = true;
2950c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				else
2951c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName << " comparison to bilinear method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage;
2952c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2953c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2954c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!levelOk)
2955c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2956c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int numFailed = compareGenMipmapBox(dst, src, errorMask.getAccess(), precision);
2957c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (numFailed == 0)
2958c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					levelOk = true;
2959c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				else
2960c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					log << tcu::TestLog::Message << "WARNING: Level " << levelNdx << ", face " << faceName <<" comparison to box method failed, found " << numFailed << " invalid pixels." << tcu::TestLog::EndMessage;
2961c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2962c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2963c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			// At this point all high-quality methods have been used.
2964c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!levelOk && result == QP_TEST_RESULT_PASS)
2965c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				result = QP_TEST_RESULT_QUALITY_WARNING;
2966c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2967c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!levelOk)
2968c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			{
2969c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				const int numFailed = compareGenMipmapVeryLenient(dst, src, errorMask.getAccess(), precision);
2970c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				if (numFailed == 0)
2971c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					levelOk = true;
2972c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				else
2973c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket					log << tcu::TestLog::Message << "ERROR: Level " << levelNdx << ", face " << faceName << " appears to contain " << numFailed << " completely wrong pixels, failing case!" << tcu::TestLog::EndMessage;
2974c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			}
2975c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2976c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!levelOk)
2977c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				result = QP_TEST_RESULT_FAIL;
2978c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2979c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			log << tcu::TestLog::ImageSet(string("Level") + de::toString(levelNdx) + "Face" + de::toString(faceNdx), string("Level ") + de::toString(levelNdx) + ", face " + string(faceName) + " result")
2980c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				<< tcu::TestLog::Image("Result", "Result", dst);
2981c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2982c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			if (!levelOk)
2983c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket				log << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
2984c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2985c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			log << tcu::TestLog::EndImageSet;
2986c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket		}
2987c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	}
2988c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2989c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return result;
2990c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
2991c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2992c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket// Logging utilities.
2993c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
2994c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siketstd::ostream& operator<< (std::ostream& str, const LogGradientFmt& fmt)
2995c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket{
2996c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket	return str << "(R: " << fmt.valueMin->x() << " -> " << fmt.valueMax->x() << ", "
2997c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			   <<  "G: " << fmt.valueMin->y() << " -> " << fmt.valueMax->y() << ", "
2998c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			   <<  "B: " << fmt.valueMin->z() << " -> " << fmt.valueMax->z() << ", "
2999c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket			   <<  "A: " << fmt.valueMin->w() << " -> " << fmt.valueMax->w() << ")";
3000c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket}
3001c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket
3002c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket} // TextureTestUtil
3003c4eb6f3271a0bcd54835e666e836e3e72beebbd2Peter Siket} // glu
3004