• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Texture access and query function tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktShaderRenderTextureFunctionTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "tcuTexture.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuTestLog.hpp"
32 #include "glwEnums.hpp"
33 #include "deMath.h"
34 #include "vkImageUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 
37 namespace vkt
38 {
39 namespace sr
40 {
41 namespace
42 {
43 
44 using tcu::Vec2;
45 using tcu::Vec3;
46 using tcu::Vec4;
47 using tcu::IVec2;
48 using tcu::IVec3;
49 using tcu::IVec4;
50 
51 using std::vector;
52 
53 enum Function
54 {
55 	FUNCTION_TEXTURE = 0,		//!< texture(), textureOffset()
56 	FUNCTION_TEXTUREPROJ,		//!< textureProj(), textureProjOffset()
57 	FUNCTION_TEXTUREPROJ3,		//!< textureProj(sampler2D, vec3)
58 	FUNCTION_TEXTURELOD,		// ...
59 	FUNCTION_TEXTUREPROJLOD,
60 	FUNCTION_TEXTUREPROJLOD3,	//!< textureProjLod(sampler2D, vec3)
61 	FUNCTION_TEXTUREGRAD,
62 	FUNCTION_TEXTUREPROJGRAD,
63 	FUNCTION_TEXTUREPROJGRAD3,	//!< textureProjGrad(sampler2D, vec3)
64 	FUNCTION_TEXELFETCH,
65 
66 	FUNCTION_LAST
67 };
68 
functionHasAutoLod(glu::ShaderType shaderType,Function function)69 inline bool functionHasAutoLod (glu::ShaderType shaderType, Function function)
70 {
71 	return shaderType == glu::SHADERTYPE_FRAGMENT &&
72 		   (function == FUNCTION_TEXTURE		||
73 			function == FUNCTION_TEXTUREPROJ	||
74 			function == FUNCTION_TEXTUREPROJ3);
75 }
76 
functionHasProj(Function function)77 inline bool functionHasProj (Function function)
78 {
79 	return function == FUNCTION_TEXTUREPROJ		||
80 		   function == FUNCTION_TEXTUREPROJ3	||
81 		   function == FUNCTION_TEXTUREPROJLOD	||
82 		   function == FUNCTION_TEXTUREPROJGRAD	||
83 		   function == FUNCTION_TEXTUREPROJLOD3	||
84 		   function == FUNCTION_TEXTUREPROJGRAD3;
85 }
86 
functionHasGrad(Function function)87 inline bool functionHasGrad (Function function)
88 {
89 	return function == FUNCTION_TEXTUREGRAD || function == FUNCTION_TEXTUREPROJGRAD || function == FUNCTION_TEXTUREPROJGRAD3;
90 }
91 
functionHasLod(Function function)92 inline bool functionHasLod (Function function)
93 {
94 	return function == FUNCTION_TEXTURELOD		||
95 		   function == FUNCTION_TEXTUREPROJLOD	||
96 		   function == FUNCTION_TEXTUREPROJLOD3	||
97 		   function == FUNCTION_TEXELFETCH;
98 }
99 
100 struct TextureLookupSpec
101 {
102 	Function		function;
103 
104 	tcu::Vec4		minCoord;
105 	tcu::Vec4		maxCoord;
106 
107 	// Bias
108 	bool			useBias;
109 
110 	// Bias or Lod for *Lod* functions
111 	float			minLodBias;
112 	float			maxLodBias;
113 
114 	// For *Grad* functions
115 	tcu::Vec3		minDX;
116 	tcu::Vec3		maxDX;
117 	tcu::Vec3		minDY;
118 	tcu::Vec3		maxDY;
119 
120 	bool			useOffset;
121 	tcu::IVec3		offset;
122 
TextureLookupSpecvkt::sr::__anon216f131a0111::TextureLookupSpec123 	TextureLookupSpec (void)
124 		: function		(FUNCTION_LAST)
125 		, minCoord		(0.0f)
126 		, maxCoord		(1.0f)
127 		, useBias		(false)
128 		, minLodBias	(0.0f)
129 		, maxLodBias	(0.0f)
130 		, minDX			(0.0f)
131 		, maxDX			(0.0f)
132 		, minDY			(0.0f)
133 		, maxDY			(0.0f)
134 		, useOffset		(false)
135 		, offset		(0)
136 	{
137 	}
138 
TextureLookupSpecvkt::sr::__anon216f131a0111::TextureLookupSpec139 	TextureLookupSpec (Function				function_,
140 					   const tcu::Vec4&		minCoord_,
141 					   const tcu::Vec4&		maxCoord_,
142 					   bool					useBias_,
143 					   float				minLodBias_,
144 					   float				maxLodBias_,
145 					   const tcu::Vec3&		minDX_,
146 					   const tcu::Vec3&		maxDX_,
147 					   const tcu::Vec3&		minDY_,
148 					   const tcu::Vec3&		maxDY_,
149 					   bool					useOffset_,
150 					   const tcu::IVec3&	offset_)
151 		: function		(function_)
152 		, minCoord		(minCoord_)
153 		, maxCoord		(maxCoord_)
154 		, useBias		(useBias_)
155 		, minLodBias	(minLodBias_)
156 		, maxLodBias	(maxLodBias_)
157 		, minDX			(minDX_)
158 		, maxDX			(maxDX_)
159 		, minDY			(minDY_)
160 		, maxDY			(maxDY_)
161 		, useOffset		(useOffset_)
162 		, offset		(offset_)
163 	{
164 	}
165 };
166 
167 enum TextureType
168 {
169 	TEXTURETYPE_1D = 0,
170 	TEXTURETYPE_2D,
171 	TEXTURETYPE_3D,
172 	TEXTURETYPE_CUBE_MAP,
173 	TEXTURETYPE_1D_ARRAY,
174 	TEXTURETYPE_2D_ARRAY,
175 	TEXTURETYPE_CUBE_ARRAY,
176 
177 	TEXTURETYPE_LAST
178 };
179 
180 struct TextureSpec
181 {
182 	TextureType			type;		//!< Texture type (2D, cubemap, ...)
183 	deUint32			format;		//!< Internal format.
184 	int					width;
185 	int					height;
186 	int					depth;
187 	int					numLevels;
188 	tcu::Sampler		sampler;
189 
TextureSpecvkt::sr::__anon216f131a0111::TextureSpec190 	TextureSpec (void)
191 		: type			(TEXTURETYPE_LAST)
192 		, format		(GL_NONE)
193 		, width			(0)
194 		, height		(0)
195 		, depth			(0)
196 		, numLevels		(0)
197 	{
198 	}
199 
TextureSpecvkt::sr::__anon216f131a0111::TextureSpec200 	TextureSpec (TextureType			type_,
201 				 deUint32				format_,
202 				 int					width_,
203 				 int					height_,
204 				 int					depth_,
205 				 int					numLevels_,
206 				 const tcu::Sampler&	sampler_)
207 		: type			(type_)
208 		, format		(format_)
209 		, width			(width_)
210 		, height		(height_)
211 		, depth			(depth_)
212 		, numLevels		(numLevels_)
213 		, sampler		(sampler_)
214 	{
215 	}
216 };
217 
218 struct TexLookupParams
219 {
220 	float				lod;
221 	tcu::IVec3			offset;
222 	tcu::Vec4			scale;
223 	tcu::Vec4			bias;
224 
TexLookupParamsvkt::sr::__anon216f131a0111::TexLookupParams225 	TexLookupParams (void)
226 		: lod		(0.0f)
227 		, offset	(0)
228 		, scale		(1.0f)
229 		, bias		(0.0f)
230 	{
231 	}
232 };
233 
234 // \note LodMode and computeLodFromDerivates functions are copied from glsTextureTestUtil
235 namespace TextureTestUtil
236 {
237 
238 enum LodMode
239 {
240 	LODMODE_EXACT = 0,		//!< Ideal lod computation.
241 	LODMODE_MIN_BOUND,		//!< Use estimation range minimum bound.
242 	LODMODE_MAX_BOUND,		//!< Use estimation range maximum bound.
243 
244 	LODMODE_LAST
245 };
246 
247 // 1D lookup LOD computation.
248 
computeLodFromDerivates(LodMode mode,float dudx,float dudy)249 float computeLodFromDerivates (LodMode mode, float dudx, float dudy)
250 {
251 	float p = 0.0f;
252 	switch (mode)
253 	{
254 		// \note [mika] Min and max bounds equal to exact with 1D textures
255 		case LODMODE_EXACT:
256 		case LODMODE_MIN_BOUND:
257 		case LODMODE_MAX_BOUND:
258 			p = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
259 			break;
260 
261 		default:
262 			DE_ASSERT(DE_FALSE);
263 	}
264 
265 	return deFloatLog2(p);
266 }
267 
268 // 2D lookup LOD computation.
269 
computeLodFromDerivates(LodMode mode,float dudx,float dvdx,float dudy,float dvdy)270 float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dudy, float dvdy)
271 {
272 	float p = 0.0f;
273 	switch (mode)
274 	{
275 		case LODMODE_EXACT:
276 			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx), deFloatSqrt(dudy*dudy + dvdy*dvdy));
277 			break;
278 
279 		case LODMODE_MIN_BOUND:
280 		case LODMODE_MAX_BOUND:
281 		{
282 			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
283 			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
284 
285 			p = mode == LODMODE_MIN_BOUND ? de::max(mu, mv) : mu + mv;
286 			break;
287 		}
288 
289 		default:
290 			DE_ASSERT(DE_FALSE);
291 	}
292 
293 	return deFloatLog2(p);
294 }
295 
296 // 3D lookup LOD computation.
297 
computeLodFromDerivates(LodMode mode,float dudx,float dvdx,float dwdx,float dudy,float dvdy,float dwdy)298 float computeLodFromDerivates (LodMode mode, float dudx, float dvdx, float dwdx, float dudy, float dvdy, float dwdy)
299 {
300 	float p = 0.0f;
301 	switch (mode)
302 	{
303 		case LODMODE_EXACT:
304 			p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx + dwdx*dwdx), deFloatSqrt(dudy*dudy + dvdy*dvdy + dwdy*dwdy));
305 			break;
306 
307 		case LODMODE_MIN_BOUND:
308 		case LODMODE_MAX_BOUND:
309 		{
310 			float mu = de::max(deFloatAbs(dudx), deFloatAbs(dudy));
311 			float mv = de::max(deFloatAbs(dvdx), deFloatAbs(dvdy));
312 			float mw = de::max(deFloatAbs(dwdx), deFloatAbs(dwdy));
313 
314 			p = mode == LODMODE_MIN_BOUND ? de::max(de::max(mu, mv), mw) : (mu + mv + mw);
315 			break;
316 		}
317 
318 		default:
319 			DE_ASSERT(DE_FALSE);
320 	}
321 
322 	return deFloatLog2(p);
323 }
324 
325 } // TextureTestUtil
326 
327 using namespace TextureTestUtil;
328 
329 static const LodMode DEFAULT_LOD_MODE = LODMODE_EXACT;
330 
computeLodFromGrad2D(const ShaderEvalContext & c)331 inline float computeLodFromGrad2D (const ShaderEvalContext& c)
332 {
333 	float w = (float)c.textures[0].tex2D->getWidth();
334 	float h = (float)c.textures[0].tex2D->getHeight();
335 	return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[1].y()*h, c.in[2].x()*w, c.in[2].y()*h);
336 }
337 
computeLodFromGrad2DArray(const ShaderEvalContext & c)338 inline float computeLodFromGrad2DArray (const ShaderEvalContext& c)
339 {
340 	float w = (float)c.textures[0].tex2DArray->getWidth();
341 	float h = (float)c.textures[0].tex2DArray->getHeight();
342 	return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[1].y()*h, c.in[2].x()*w, c.in[2].y()*h);
343 }
344 
computeLodFromGrad3D(const ShaderEvalContext & c)345 inline float computeLodFromGrad3D (const ShaderEvalContext& c)
346 {
347 	float w = (float)c.textures[0].tex3D->getWidth();
348 	float h = (float)c.textures[0].tex3D->getHeight();
349 	float d = (float)c.textures[0].tex3D->getDepth();
350 	return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*w, c.in[1].y()*h, c.in[1].z()*d, c.in[2].x()*w, c.in[2].y()*h, c.in[2].z()*d);
351 }
352 
computeLodFromGradCube(const ShaderEvalContext & c)353 inline float computeLodFromGradCube (const ShaderEvalContext& c)
354 {
355 	// \note Major axis is always -Z or +Z
356 	float m = de::abs(c.in[0].z());
357 	float d = (float)c.textures[0].texCube->getSize();
358 	float s = d/(2.0f*m);
359 	float t = d/(2.0f*m);
360 	return computeLodFromDerivates(DEFAULT_LOD_MODE, c.in[1].x()*s, c.in[1].y()*t, c.in[2].x()*s, c.in[2].y()*t);
361 }
362 
363 typedef void (*TexEvalFunc) (ShaderEvalContext& c, const TexLookupParams& lookupParams);
364 
texture2D(const ShaderEvalContext & c,float s,float t,float lod)365 inline Vec4 texture2D		(const ShaderEvalContext& c, float s, float t, float lod)			{ return c.textures[0].tex2D->sample(c.textures[0].sampler, s, t, lod);			}
textureCube(const ShaderEvalContext & c,float s,float t,float r,float lod)366 inline Vec4 textureCube		(const ShaderEvalContext& c, float s, float t, float r, float lod)	{ return c.textures[0].texCube->sample(c.textures[0].sampler, s, t, r, lod);	}
texture2DArray(const ShaderEvalContext & c,float s,float t,float r,float lod)367 inline Vec4 texture2DArray	(const ShaderEvalContext& c, float s, float t, float r, float lod)	{ return c.textures[0].tex2DArray->sample(c.textures[0].sampler, s, t, r, lod);	}
texture3D(const ShaderEvalContext & c,float s,float t,float r,float lod)368 inline Vec4 texture3D		(const ShaderEvalContext& c, float s, float t, float r, float lod)	{ return c.textures[0].tex3D->sample(c.textures[0].sampler, s, t, r, lod);		}
369 
texture2DShadow(const ShaderEvalContext & c,float ref,float s,float t,float lod)370 inline float texture2DShadow		(const ShaderEvalContext& c, float ref, float s, float t, float lod) { return c.textures[0].tex2D->sampleCompare(c.textures[0].sampler, ref, s, t, lod); }
textureCubeShadow(const ShaderEvalContext & c,float ref,float s,float t,float r,float lod)371 inline float textureCubeShadow		(const ShaderEvalContext& c, float ref, float s, float t, float r, float lod) { return c.textures[0].texCube->sampleCompare(c.textures[0].sampler, ref, s, t, r, lod); }
texture2DArrayShadow(const ShaderEvalContext & c,float ref,float s,float t,float r,float lod)372 inline float texture2DArrayShadow	(const ShaderEvalContext& c, float ref, float s, float t, float r, float lod) { return c.textures[0].tex2DArray->sampleCompare(c.textures[0].sampler, ref, s, t, r, lod); }
373 
texture2DOffset(const ShaderEvalContext & c,float s,float t,float lod,IVec2 offset)374 inline Vec4 texture2DOffset			(const ShaderEvalContext& c, float s, float t, float lod, IVec2 offset)			{ return c.textures[0].tex2D->sampleOffset(c.textures[0].sampler, s, t, lod, offset);			}
texture2DArrayOffset(const ShaderEvalContext & c,float s,float t,float r,float lod,IVec2 offset)375 inline Vec4 texture2DArrayOffset	(const ShaderEvalContext& c, float s, float t, float r, float lod, IVec2 offset)	{ return c.textures[0].tex2DArray->sampleOffset(c.textures[0].sampler, s, t, r, lod, offset);	}
texture3DOffset(const ShaderEvalContext & c,float s,float t,float r,float lod,IVec3 offset)376 inline Vec4 texture3DOffset			(const ShaderEvalContext& c, float s, float t, float r, float lod, IVec3 offset)	{ return c.textures[0].tex3D->sampleOffset(c.textures[0].sampler, s, t, r, lod, offset);		}
377 
texture2DShadowOffset(const ShaderEvalContext & c,float ref,float s,float t,float lod,IVec2 offset)378 inline float texture2DShadowOffset		(const ShaderEvalContext& c, float ref, float s, float t, float lod, IVec2 offset)	{ return c.textures[0].tex2D->sampleCompareOffset(c.textures[0].sampler, ref, s, t, lod, offset); }
texture2DArrayShadowOffset(const ShaderEvalContext & c,float ref,float s,float t,float r,float lod,IVec2 offset)379 inline float texture2DArrayShadowOffset	(const ShaderEvalContext& c, float ref, float s, float t, float r, float lod, IVec2 offset) { return c.textures[0].tex2DArray->sampleCompareOffset(c.textures[0].sampler, ref, s, t, r, lod, offset); }
380 
381 // Eval functions.
evalTexture2D(ShaderEvalContext & c,const TexLookupParams & p)382 static void		evalTexture2D			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod)*p.scale + p.bias; }
evalTextureCube(ShaderEvalContext & c,const TexLookupParams & p)383 static void		evalTextureCube			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; }
evalTexture2DArray(ShaderEvalContext & c,const TexLookupParams & p)384 static void		evalTexture2DArray		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; }
evalTexture3D(ShaderEvalContext & c,const TexLookupParams & p)385 static void		evalTexture3D			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; }
386 
evalTexture2DBias(ShaderEvalContext & c,const TexLookupParams & p)387 static void		evalTexture2DBias		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x())*p.scale + p.bias; }
evalTextureCubeBias(ShaderEvalContext & c,const TexLookupParams & p)388 static void		evalTextureCubeBias		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
evalTexture2DArrayBias(ShaderEvalContext & c,const TexLookupParams & p)389 static void		evalTexture2DArrayBias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
evalTexture3DBias(ShaderEvalContext & c,const TexLookupParams & p)390 static void		evalTexture3DBias		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
391 
evalTexture2DProj3(ShaderEvalContext & c,const TexLookupParams & p)392 static void		evalTexture2DProj3		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod)*p.scale + p.bias; }
evalTexture2DProj3Bias(ShaderEvalContext & c,const TexLookupParams & p)393 static void		evalTexture2DProj3Bias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
evalTexture2DProj(ShaderEvalContext & c,const TexLookupParams & p)394 static void		evalTexture2DProj		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod)*p.scale + p.bias; }
evalTexture2DProjBias(ShaderEvalContext & c,const TexLookupParams & p)395 static void		evalTexture2DProjBias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x())*p.scale + p.bias; }
evalTexture3DProj(ShaderEvalContext & c,const TexLookupParams & p)396 static void		evalTexture3DProj		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod)*p.scale + p.bias; }
evalTexture3DProjBias(ShaderEvalContext & c,const TexLookupParams & p)397 static void		evalTexture3DProjBias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod+c.in[1].x())*p.scale + p.bias; }
398 
evalTexture2DLod(ShaderEvalContext & c,const TexLookupParams & p)399 static void		evalTexture2DLod		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x(), c.in[0].y(), c.in[1].x())*p.scale + p.bias; }
evalTextureCubeLod(ShaderEvalContext & c,const TexLookupParams & p)400 static void		evalTextureCubeLod		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
evalTexture2DArrayLod(ShaderEvalContext & c,const TexLookupParams & p)401 static void		evalTexture2DArrayLod	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
evalTexture3DLod(ShaderEvalContext & c,const TexLookupParams & p)402 static void		evalTexture3DLod		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
403 
evalTexture2DProjLod3(ShaderEvalContext & c,const TexLookupParams & p)404 static void		evalTexture2DProjLod3	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
evalTexture2DProjLod(ShaderEvalContext & c,const TexLookupParams & p)405 static void		evalTexture2DProjLod	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x())*p.scale + p.bias; }
evalTexture3DProjLod(ShaderEvalContext & c,const TexLookupParams & p)406 static void		evalTexture3DProjLod	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), c.in[1].x())*p.scale + p.bias; }
407 
408 // Offset variants
409 
evalTexture2DOffset(ShaderEvalContext & c,const TexLookupParams & p)410 static void		evalTexture2DOffset				(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DArrayOffset(ShaderEvalContext & c,const TexLookupParams & p)411 static void		evalTexture2DArrayOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture3DOffset(ShaderEvalContext & c,const TexLookupParams & p)412 static void		evalTexture3DOffset				(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod, p.offset)*p.scale + p.bias; }
413 
evalTexture2DOffsetBias(ShaderEvalContext & c,const TexLookupParams & p)414 static void		evalTexture2DOffsetBias			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DArrayOffsetBias(ShaderEvalContext & c,const TexLookupParams & p)415 static void		evalTexture2DArrayOffsetBias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture3DOffsetBias(ShaderEvalContext & c,const TexLookupParams & p)416 static void		evalTexture3DOffsetBias			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x(), p.offset)*p.scale + p.bias; }
417 
evalTexture2DLodOffset(ShaderEvalContext & c,const TexLookupParams & p)418 static void		evalTexture2DLodOffset			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DArrayLodOffset(ShaderEvalContext & c,const TexLookupParams & p)419 static void		evalTexture2DArrayLodOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture3DLodOffset(ShaderEvalContext & c,const TexLookupParams & p)420 static void		evalTexture3DLodOffset			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x(), p.offset)*p.scale + p.bias; }
421 
evalTexture2DProj3Offset(ShaderEvalContext & c,const TexLookupParams & p)422 static void		evalTexture2DProj3Offset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DProj3OffsetBias(ShaderEvalContext & c,const TexLookupParams & p)423 static void		evalTexture2DProj3OffsetBias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DProjOffset(ShaderEvalContext & c,const TexLookupParams & p)424 static void		evalTexture2DProjOffset			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod, p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DProjOffsetBias(ShaderEvalContext & c,const TexLookupParams & p)425 static void		evalTexture2DProjOffsetBias		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture3DProjOffset(ShaderEvalContext & c,const TexLookupParams & p)426 static void		evalTexture3DProjOffset			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod, p.offset)*p.scale + p.bias; }
evalTexture3DProjOffsetBias(ShaderEvalContext & c,const TexLookupParams & p)427 static void		evalTexture3DProjOffsetBias		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), p.lod+c.in[1].x(), p.offset)*p.scale + p.bias; }
428 
evalTexture2DProjLod3Offset(ShaderEvalContext & c,const TexLookupParams & p)429 static void		evalTexture2DProjLod3Offset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DProjLodOffset(ShaderEvalContext & c,const TexLookupParams & p)430 static void		evalTexture2DProjLodOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x(), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture3DProjLodOffset(ShaderEvalContext & c,const TexLookupParams & p)431 static void		evalTexture3DProjLodOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), c.in[1].x(), p.offset)*p.scale + p.bias; }
432 
433 // Shadow variants
434 
evalTexture2DShadow(ShaderEvalContext & c,const TexLookupParams & p)435 static void		evalTexture2DShadow				(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod); }
evalTexture2DShadowBias(ShaderEvalContext & c,const TexLookupParams & p)436 static void		evalTexture2DShadowBias			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x()); }
437 
evalTextureCubeShadow(ShaderEvalContext & c,const TexLookupParams & p)438 static void		evalTextureCubeShadow			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = textureCubeShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod); }
evalTextureCubeShadowBias(ShaderEvalContext & c,const TexLookupParams & p)439 static void		evalTextureCubeShadowBias		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = textureCubeShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x()); }
440 
evalTexture2DArrayShadow(ShaderEvalContext & c,const TexLookupParams & p)441 static void		evalTexture2DArrayShadow		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DArrayShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod); }
442 
evalTexture2DShadowLod(ShaderEvalContext & c,const TexLookupParams &)443 static void		evalTexture2DShadowLod			(ShaderEvalContext& c, const TexLookupParams&)		{ c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), c.in[1].x()); }
evalTexture2DShadowLodOffset(ShaderEvalContext & c,const TexLookupParams & p)444 static void		evalTexture2DShadowLodOffset	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), c.in[1].x(), p.offset.swizzle(0,1)); }
445 
evalTexture2DShadowProj(ShaderEvalContext & c,const TexLookupParams & p)446 static void		evalTexture2DShadowProj			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod); }
evalTexture2DShadowProjBias(ShaderEvalContext & c,const TexLookupParams & p)447 static void		evalTexture2DShadowProjBias		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x()); }
448 
evalTexture2DShadowProjLod(ShaderEvalContext & c,const TexLookupParams &)449 static void		evalTexture2DShadowProjLod		(ShaderEvalContext& c, const TexLookupParams&)		{ c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x()); }
evalTexture2DShadowProjLodOffset(ShaderEvalContext & c,const TexLookupParams & p)450 static void		evalTexture2DShadowProjLodOffset(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x(), p.offset.swizzle(0,1)); }
451 
evalTexture2DShadowOffset(ShaderEvalContext & c,const TexLookupParams & p)452 static void		evalTexture2DShadowOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod, p.offset.swizzle(0,1)); }
evalTexture2DShadowOffsetBias(ShaderEvalContext & c,const TexLookupParams & p)453 static void		evalTexture2DShadowOffsetBias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x(), p.offset.swizzle(0,1)); }
454 
evalTexture2DShadowProjOffset(ShaderEvalContext & c,const TexLookupParams & p)455 static void		evalTexture2DShadowProjOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod, p.offset.swizzle(0,1)); }
evalTexture2DShadowProjOffsetBias(ShaderEvalContext & c,const TexLookupParams & p)456 static void		evalTexture2DShadowProjOffsetBias	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x(), p.offset.swizzle(0,1)); }
457 
458 // Gradient variarts
459 
evalTexture2DGrad(ShaderEvalContext & c,const TexLookupParams & p)460 static void		evalTexture2DGrad		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c))*p.scale + p.bias; }
evalTextureCubeGrad(ShaderEvalContext & c,const TexLookupParams & p)461 static void		evalTextureCubeGrad		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGradCube(c))*p.scale + p.bias; }
evalTexture2DArrayGrad(ShaderEvalContext & c,const TexLookupParams & p)462 static void		evalTexture2DArrayGrad	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArray(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c))*p.scale + p.bias; }
evalTexture3DGrad(ShaderEvalContext & c,const TexLookupParams & p)463 static void		evalTexture3DGrad		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad3D(c))*p.scale + p.bias; }
464 
evalTexture2DShadowGrad(ShaderEvalContext & c,const TexLookupParams &)465 static void		evalTexture2DShadowGrad			(ShaderEvalContext& c, const TexLookupParams&)		{ c.color.x() = texture2DShadow(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c)); }
evalTextureCubeShadowGrad(ShaderEvalContext & c,const TexLookupParams &)466 static void		evalTextureCubeShadowGrad		(ShaderEvalContext& c, const TexLookupParams&)		{ c.color.x() = textureCubeShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGradCube(c)); }
evalTexture2DArrayShadowGrad(ShaderEvalContext & c,const TexLookupParams &)467 static void		evalTexture2DArrayShadowGrad	(ShaderEvalContext& c, const TexLookupParams&)		{ c.color.x() = texture2DArrayShadow(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c)); }
468 
evalTexture2DGradOffset(ShaderEvalContext & c,const TexLookupParams & p)469 static void		evalTexture2DGradOffset			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DArrayGradOffset(ShaderEvalContext & c,const TexLookupParams & p)470 static void		evalTexture2DArrayGradOffset	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DArrayOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture3DGradOffset(ShaderEvalContext & c,const TexLookupParams & p)471 static void		evalTexture3DGradOffset			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad3D(c), p.offset)*p.scale + p.bias; }
472 
evalTexture2DShadowGradOffset(ShaderEvalContext & c,const TexLookupParams & p)473 static void		evalTexture2DShadowGradOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z(), c.in[0].x(), c.in[0].y(), computeLodFromGrad2D(c), p.offset.swizzle(0,1)); }
evalTexture2DArrayShadowGradOffset(ShaderEvalContext & c,const TexLookupParams & p)474 static void		evalTexture2DArrayShadowGradOffset	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DArrayShadowOffset(c, c.in[0].w(), c.in[0].x(), c.in[0].y(), c.in[0].z(), computeLodFromGrad2DArray(c), p.offset.swizzle(0,1)); }
475 
evalTexture2DShadowProjGrad(ShaderEvalContext & c,const TexLookupParams &)476 static void		evalTexture2DShadowProjGrad			(ShaderEvalContext& c, const TexLookupParams&)		{ c.color.x() = texture2DShadow(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), computeLodFromGrad2D(c)); }
evalTexture2DShadowProjGradOffset(ShaderEvalContext & c,const TexLookupParams & p)477 static void		evalTexture2DShadowProjGradOffset	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color.x() = texture2DShadowOffset(c, c.in[0].z()/c.in[0].w(), c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), computeLodFromGrad2D(c), p.offset.swizzle(0,1)); }
478 
evalTexture2DProjGrad3(ShaderEvalContext & c,const TexLookupParams & p)479 static void		evalTexture2DProjGrad3			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), computeLodFromGrad2D(c))*p.scale + p.bias; }
evalTexture2DProjGrad(ShaderEvalContext & c,const TexLookupParams & p)480 static void		evalTexture2DProjGrad			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), computeLodFromGrad2D(c))*p.scale + p.bias; }
evalTexture3DProjGrad(ShaderEvalContext & c,const TexLookupParams & p)481 static void		evalTexture3DProjGrad			(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), computeLodFromGrad3D(c))*p.scale + p.bias; }
482 
evalTexture2DProjGrad3Offset(ShaderEvalContext & c,const TexLookupParams & p)483 static void		evalTexture2DProjGrad3Offset	(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), computeLodFromGrad2D(c), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture2DProjGradOffset(ShaderEvalContext & c,const TexLookupParams & p)484 static void		evalTexture2DProjGradOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture2DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), computeLodFromGrad2D(c), p.offset.swizzle(0,1))*p.scale + p.bias; }
evalTexture3DProjGradOffset(ShaderEvalContext & c,const TexLookupParams & p)485 static void		evalTexture3DProjGradOffset		(ShaderEvalContext& c, const TexLookupParams& p)	{ c.color = texture3DOffset(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[0].z()/c.in[0].w(), computeLodFromGrad3D(c), p.offset)*p.scale + p.bias; }
486 
487 // Texel fetch variants
488 
evalTexelFetch2D(ShaderEvalContext & c,const TexLookupParams & p)489 static void evalTexelFetch2D (ShaderEvalContext& c, const TexLookupParams& p)
490 {
491 	int	x	= deChopFloatToInt32(c.in[0].x())+p.offset.x();
492 	int	y	= deChopFloatToInt32(c.in[0].y())+p.offset.y();
493 	int	lod = deChopFloatToInt32(c.in[1].x());
494 	c.color = c.textures[0].tex2D->getLevel(lod).getPixel(x, y)*p.scale + p.bias;
495 }
496 
evalTexelFetch2DArray(ShaderEvalContext & c,const TexLookupParams & p)497 static void evalTexelFetch2DArray (ShaderEvalContext& c, const TexLookupParams& p)
498 {
499 	int	x	= deChopFloatToInt32(c.in[0].x())+p.offset.x();
500 	int	y	= deChopFloatToInt32(c.in[0].y())+p.offset.y();
501 	int	l	= deChopFloatToInt32(c.in[0].z());
502 	int	lod = deChopFloatToInt32(c.in[1].x());
503 	c.color = c.textures[0].tex2DArray->getLevel(lod).getPixel(x, y, l)*p.scale + p.bias;
504 }
505 
evalTexelFetch3D(ShaderEvalContext & c,const TexLookupParams & p)506 static void evalTexelFetch3D (ShaderEvalContext& c, const TexLookupParams& p)
507 {
508 	int	x	= deChopFloatToInt32(c.in[0].x())+p.offset.x();
509 	int	y	= deChopFloatToInt32(c.in[0].y())+p.offset.y();
510 	int	z	= deChopFloatToInt32(c.in[0].z())+p.offset.z();
511 	int	lod = deChopFloatToInt32(c.in[1].x());
512 	c.color = c.textures[0].tex3D->getLevel(lod).getPixel(x, y, z)*p.scale + p.bias;
513 }
514 
515 class TexLookupEvaluator : public ShaderEvaluator
516 {
517 public:
TexLookupEvaluator(TexEvalFunc evalFunc,const TexLookupParams & lookupParams)518 							TexLookupEvaluator		(TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {}
~TexLookupEvaluator(void)519 	virtual					~TexLookupEvaluator		(void) {}
520 
evaluate(ShaderEvalContext & ctx) const521 	virtual void			evaluate				(ShaderEvalContext& ctx) const { m_evalFunc(ctx, m_lookupParams); }
522 
523 private:
524 	TexEvalFunc				m_evalFunc;
525 	const TexLookupParams&	m_lookupParams;
526 };
527 
528 class ShaderTextureFunctionInstance : public ShaderRenderCaseInstance
529 {
530 public:
531 								ShaderTextureFunctionInstance		(Context&					context,
532 																	 const bool					isVertexCase,
533 																	 const ShaderEvaluator&		evaluator,
534 																	 const UniformSetup&		uniformSetup,
535 																	 const TextureLookupSpec&	lookupSpec,
536 																	 const TextureSpec&			textureSpec,
537 																	 const TexLookupParams&		lookupParams,
538 																	 const ImageBackingMode		imageBackingMode = IMAGE_BACKING_MODE_REGULAR);
539 	virtual						~ShaderTextureFunctionInstance		(void);
540 
541 protected:
542 	virtual void				setupUniforms						(const tcu::Vec4&);
543 	void						initTexture							(void);
544 private:
545 	const TextureLookupSpec&	m_lookupSpec;
546 	const TextureSpec&			m_textureSpec;
547 	const TexLookupParams&		m_lookupParams;
548 };
549 
ShaderTextureFunctionInstance(Context & context,const bool isVertexCase,const ShaderEvaluator & evaluator,const UniformSetup & uniformSetup,const TextureLookupSpec & lookupSpec,const TextureSpec & textureSpec,const TexLookupParams & lookupParams,const ImageBackingMode imageBackingMode)550 ShaderTextureFunctionInstance::ShaderTextureFunctionInstance (Context&						context,
551 															  const bool					isVertexCase,
552 															  const ShaderEvaluator&		evaluator,
553 															  const UniformSetup&			uniformSetup,
554 															  const TextureLookupSpec&		lookupSpec,
555 															  const TextureSpec&			textureSpec,
556 															  const TexLookupParams&		lookupParams,
557 															  const ImageBackingMode		imageBackingMode)
558 	: ShaderRenderCaseInstance	(context, isVertexCase, evaluator, uniformSetup, DE_NULL, imageBackingMode)
559 	, m_lookupSpec				(lookupSpec)
560 	, m_textureSpec				(textureSpec)
561 	, m_lookupParams			(lookupParams)
562 {
563 	{
564 		// Base coord scale & bias
565 		Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord;
566 		Vec4 b = m_lookupSpec.minCoord;
567 
568 		float baseCoordTrans[] =
569 		{
570 			s.x(),		0.0f,		0.f,	b.x(),
571 			0.f,		s.y(),		0.f,	b.y(),
572 			s.z()/2.f,	-s.z()/2.f,	0.f,	s.z()/2.f + b.z(),
573 			-s.w()/2.f,	s.w()/2.f,	0.f,	s.w()/2.f + b.w()
574 		};
575 
576 		m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans));
577 
578 		useAttribute(4u, A_IN0);
579 	}
580 
581 	bool hasLodBias	= functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias;
582 	bool isGrad		= functionHasGrad(m_lookupSpec.function);
583 	DE_ASSERT(!isGrad || !hasLodBias);
584 
585 	if (hasLodBias)
586 	{
587 		float s = m_lookupSpec.maxLodBias-m_lookupSpec.minLodBias;
588 		float b = m_lookupSpec.minLodBias;
589 		float lodCoordTrans[] =
590 		{
591 			s/2.0f,		s/2.0f,		0.f,	b,
592 			0.0f,		0.0f,		0.0f,	0.0f,
593 			0.0f,		0.0f,		0.0f,	0.0f,
594 			0.0f,		0.0f,		0.0f,	0.0f
595 		};
596 
597 		m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans));
598 
599 		useAttribute(5u, A_IN1);
600 	}
601 	else if (isGrad)
602 	{
603 		Vec3 sx = m_lookupSpec.maxDX-m_lookupSpec.minDX;
604 		Vec3 sy = m_lookupSpec.maxDY-m_lookupSpec.minDY;
605 		float gradDxTrans[] =
606 		{
607 			sx.x()/2.0f,	sx.x()/2.0f,	0.f,	m_lookupSpec.minDX.x(),
608 			sx.y()/2.0f,	sx.y()/2.0f,	0.0f,	m_lookupSpec.minDX.y(),
609 			sx.z()/2.0f,	sx.z()/2.0f,	0.0f,	m_lookupSpec.minDX.z(),
610 			0.0f,			0.0f,			0.0f,	0.0f
611 		};
612 		float gradDyTrans[] =
613 		{
614 			-sy.x()/2.0f,	-sy.x()/2.0f,	0.f,	m_lookupSpec.maxDY.x(),
615 			-sy.y()/2.0f,	-sy.y()/2.0f,	0.0f,	m_lookupSpec.maxDY.y(),
616 			-sy.z()/2.0f,	-sy.z()/2.0f,	0.0f,	m_lookupSpec.maxDY.z(),
617 			0.0f,			0.0f,			0.0f,	0.0f
618 		};
619 
620 		m_userAttribTransforms.push_back(tcu::Mat4(gradDxTrans));
621 		m_userAttribTransforms.push_back(tcu::Mat4(gradDyTrans));
622 
623 		useAttribute(5u, A_IN1);
624 		useAttribute(6u, A_IN2);
625 	}
626 
627 	initTexture();
628 }
629 
~ShaderTextureFunctionInstance(void)630 ShaderTextureFunctionInstance::~ShaderTextureFunctionInstance (void)
631 {
632 }
633 
setupUniforms(const tcu::Vec4 &)634 void ShaderTextureFunctionInstance::setupUniforms (const tcu::Vec4&)
635 {
636 	useSampler(0u, 0u);
637 	addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec4), m_lookupParams.scale.getPtr());
638 	addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec4), m_lookupParams.bias.getPtr());
639 }
640 
initTexture(void)641 void ShaderTextureFunctionInstance::initTexture (void)
642 {
643 	static const IVec4		texCubeSwz[] =
644 	{
645 		IVec4(0,0,1,1),
646 		IVec4(1,1,0,0),
647 		IVec4(0,1,0,1),
648 		IVec4(1,0,1,0),
649 		IVec4(0,1,1,0),
650 		IVec4(1,0,0,1)
651 	};
652 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST);
653 
654 	tcu::TextureFormat		texFmt			= glu::mapGLInternalFormat(m_textureSpec.format);
655 	tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
656 	tcu::UVec2				viewportSize	= getViewportSize();
657 	bool					isProj			= functionHasProj(m_lookupSpec.function);
658 	bool					isAutoLod		= functionHasAutoLod(m_isVertexCase ? glu::SHADERTYPE_VERTEX : glu::SHADERTYPE_FRAGMENT,
659 																 m_lookupSpec.function); // LOD can vary significantly
660 	float					proj			= isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f;
661 	TexLookupParams			lookupParams;
662 
663 	switch (m_textureSpec.type)
664 	{
665 		case TEXTURETYPE_2D:
666 		{
667 			float								levelStep		= isAutoLod ? 0.0f : 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
668 			Vec4								cScale			= fmtInfo.valueMax-fmtInfo.valueMin;
669 			Vec4								cBias			= fmtInfo.valueMin;
670 			int									baseCellSize	= de::min(m_textureSpec.width/4, m_textureSpec.height/4);
671 			de::MovePtr<tcu::Texture2D>			texture2D;
672 
673 			texture2D = de::MovePtr<tcu::Texture2D>(new tcu::Texture2D(texFmt, m_textureSpec.width, m_textureSpec.height));
674 
675 			for (int level = 0; level < m_textureSpec.numLevels; level++)
676 			{
677 				float	fA		= float(level)*levelStep;
678 				float	fB		= 1.0f-fA;
679 				Vec4	colorA	= cBias + cScale*Vec4(fA, fB, fA, fB);
680 				Vec4	colorB	= cBias + cScale*Vec4(fB, fA, fB, fA);
681 
682 				texture2D->allocLevel(level);
683 				tcu::fillWithGrid(texture2D->getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB);
684 			}
685 
686 			// Compute LOD.
687 			float	dudx	= (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width	/ (float)viewportSize[0];
688 			float	dvdy	= (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height	/ (float)viewportSize[1];
689 			lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, 0.0f, dvdy);
690 
691 			// Append to texture list.
692 			m_textures.push_back(TextureBindingSp(new TextureBinding(texture2D.release(), m_textureSpec.sampler)));
693 			break;
694 		}
695 
696 		case TEXTURETYPE_CUBE_MAP:
697 		{
698 			float								levelStep		= isAutoLod ? 0.0f : 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
699 			Vec4								cScale			= fmtInfo.valueMax-fmtInfo.valueMin;
700 			Vec4								cBias			= fmtInfo.valueMin;
701 			Vec4								cCorner			= cBias + cScale*0.5f;
702 			int									baseCellSize	= de::min(m_textureSpec.width/4, m_textureSpec.height/4);
703 			de::MovePtr<tcu::TextureCube>		textureCube;
704 
705 			DE_ASSERT(m_textureSpec.width == m_textureSpec.height);
706 			textureCube = de::MovePtr<tcu::TextureCube>(new tcu::TextureCube(texFmt, m_textureSpec.width));
707 
708 			for (int level = 0; level < m_textureSpec.numLevels; level++)
709 			{
710 				float	fA		= float(level)*levelStep;
711 				float	fB		= 1.0f-fA;
712 				Vec2	f		(fA, fB);
713 
714 				for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
715 				{
716 					const IVec4&	swzA	= texCubeSwz[face];
717 					IVec4			swzB	= 1-swzA;
718 					Vec4			colorA	= cBias + cScale*f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]);
719 					Vec4			colorB	= cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]);
720 
721 					textureCube->allocLevel((tcu::CubeFace)face, level);
722 
723 					{
724 						const tcu::PixelBufferAccess	access		= textureCube->getLevelFace(level, (tcu::CubeFace)face);
725 						const int						lastPix		= access.getWidth()-1;
726 
727 						tcu::fillWithGrid(access, de::max(1, baseCellSize>>level), colorA, colorB);
728 
729 						// Ensure all corners have identical colors in order to avoid dealing with ambiguous corner texel filtering
730 						access.setPixel(cCorner, 0, 0);
731 						access.setPixel(cCorner, 0, lastPix);
732 						access.setPixel(cCorner, lastPix, 0);
733 						access.setPixel(cCorner, lastPix, lastPix);
734 					}
735 				}
736 			}
737 
738 			// Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
739 			DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005);
740 			DE_ASSERT(de::abs(m_lookupSpec.minCoord[0]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[0]) < de::abs(m_lookupSpec.minCoord[2]));
741 			DE_ASSERT(de::abs(m_lookupSpec.minCoord[1]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[1]) < de::abs(m_lookupSpec.minCoord[2]));
742 
743 			tcu::CubeFaceFloatCoords	c00		= tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
744 			tcu::CubeFaceFloatCoords	c10		= tcu::getCubeFaceCoords(Vec3(m_lookupSpec.maxCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
745 			tcu::CubeFaceFloatCoords	c01		= tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.maxCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
746 			float						dudx	= (c10.s - c00.s)*(float)m_textureSpec.width	/ (float)viewportSize[0];
747 			float						dvdy	= (c01.t - c00.t)*(float)m_textureSpec.height	/ (float)viewportSize[1];
748 			lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, 0.0f, dvdy);
749 
750 			// Append to texture list.
751 			m_textures.push_back(TextureBindingSp(new TextureBinding(textureCube.release(), m_textureSpec.sampler)));
752 			break;
753 		}
754 
755 		case TEXTURETYPE_2D_ARRAY:
756 		{
757 			float								layerStep		= 1.0f / (float)m_textureSpec.depth;
758 			float								levelStep		= isAutoLod ? 0.0f : 1.0f / (float)(de::max(1, m_textureSpec.numLevels-1)*m_textureSpec.depth);
759 			Vec4								cScale			= fmtInfo.valueMax-fmtInfo.valueMin;
760 			Vec4								cBias			= fmtInfo.valueMin;
761 			int									baseCellSize	= de::min(m_textureSpec.width/4, m_textureSpec.height/4);
762 			de::MovePtr<tcu::Texture2DArray>	texture2DArray;
763 
764 			texture2DArray = de::MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(texFmt, m_textureSpec.width, m_textureSpec.height, m_textureSpec.depth));
765 
766 			for (int level = 0; level < m_textureSpec.numLevels; level++)
767 			{
768 				texture2DArray->allocLevel(level);
769 				tcu::PixelBufferAccess levelAccess = texture2DArray->getLevel(level);
770 
771 				for (int layer = 0; layer < levelAccess.getDepth(); layer++)
772 				{
773 					float	fA		= (float)layer*layerStep + (float)level*levelStep;
774 					float	fB		= 1.0f-fA;
775 					Vec4	colorA	= cBias + cScale*Vec4(fA, fB, fA, fB);
776 					Vec4	colorB	= cBias + cScale*Vec4(fB, fA, fB, fA);
777 
778 					tcu::fillWithGrid(tcu::getSubregion(levelAccess, 0, 0, layer, levelAccess.getWidth(), levelAccess.getHeight(), 1), de::max(1, baseCellSize>>level), colorA, colorB);
779 				}
780 			}
781 
782 			// Compute LOD.
783 			float	dudx	= (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width	/ (float)viewportSize[0];
784 			float	dvdy	= (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height	/ (float)viewportSize[1];
785 			lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, 0.0f, dvdy);
786 
787 			// Append to texture list.
788 			m_textures.push_back(TextureBindingSp(new TextureBinding(texture2DArray.release(), m_textureSpec.sampler)));
789 			break;
790 		}
791 
792 		case TEXTURETYPE_3D:
793 		{
794 			float								levelStep		= isAutoLod ? 0.0f : 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
795 			Vec4								cScale			= fmtInfo.valueMax-fmtInfo.valueMin;
796 			Vec4								cBias			= fmtInfo.valueMin;
797 			int									baseCellSize	= de::min(de::min(m_textureSpec.width/2, m_textureSpec.height/2), m_textureSpec.depth/2);
798 			de::MovePtr<tcu::Texture3D>			texture3D;
799 
800 			texture3D = de::MovePtr<tcu::Texture3D>(new tcu::Texture3D(texFmt, m_textureSpec.width, m_textureSpec.height, m_textureSpec.depth));
801 
802 			for (int level = 0; level < m_textureSpec.numLevels; level++)
803 			{
804 				float	fA		= (float)level*levelStep;
805 				float	fB		= 1.0f-fA;
806 				Vec4	colorA	= cBias + cScale*Vec4(fA, fB, fA, fB);
807 				Vec4	colorB	= cBias + cScale*Vec4(fB, fA, fB, fA);
808 
809 				texture3D->allocLevel(level);
810 				tcu::fillWithGrid(texture3D->getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB);
811 			}
812 
813 			// Compute LOD.
814 			float	dudx	= (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width		/ (float)viewportSize[0];
815 			float	dvdy	= (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height		/ (float)viewportSize[1];
816 			float	dwdx	= (m_lookupSpec.maxCoord[2]-m_lookupSpec.minCoord[2])*0.5f*proj*(float)m_textureSpec.depth	/ (float)viewportSize[0];
817 			float	dwdy	= (m_lookupSpec.maxCoord[2]-m_lookupSpec.minCoord[2])*0.5f*proj*(float)m_textureSpec.depth	/ (float)viewportSize[1];
818 			lookupParams.lod = computeLodFromDerivates(DEFAULT_LOD_MODE, dudx, 0.0f, dwdx, 0.0f, dvdy, dwdy);
819 
820 			// Append to texture list.
821 			m_textures.push_back(TextureBindingSp(new TextureBinding(texture3D.release(), m_textureSpec.sampler)));
822 			break;
823 		}
824 
825 		default:
826 			DE_ASSERT(DE_FALSE);
827 	}
828 
829 	// Set lookup scale & bias
830 	lookupParams.scale		= fmtInfo.lookupScale;
831 	lookupParams.bias		= fmtInfo.lookupBias;
832 	lookupParams.offset		= m_lookupSpec.offset;
833 
834 	// \todo [dirnerakos] Avoid const cast somehow
835 	const_cast<TexLookupParams&>(m_lookupParams) = lookupParams;
836 }
837 
838 class ShaderTextureFunctionCase : public ShaderRenderCase
839 {
840 public:
841 								ShaderTextureFunctionCase		(tcu::TestContext&				testCtx,
842 																 const std::string&				name,
843 																 const std::string&				desc,
844 																 const TextureLookupSpec&		lookup,
845 																 const TextureSpec&				texture,
846 																 TexEvalFunc					evalFunc,
847 																 bool							isVertexCase);
848 	virtual						~ShaderTextureFunctionCase		(void);
849 
850 	virtual TestInstance*		createInstance					(Context& context) const;
851 
852 protected:
853 	const TextureLookupSpec		m_lookupSpec;
854 	const TextureSpec			m_textureSpec;
855 	const TexLookupParams		m_lookupParams;
856 
857 	void						initShaderSources				(void);
858 };
859 
ShaderTextureFunctionCase(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,const TextureLookupSpec & lookup,const TextureSpec & texture,TexEvalFunc evalFunc,bool isVertexCase)860 ShaderTextureFunctionCase::ShaderTextureFunctionCase (tcu::TestContext&				testCtx,
861 													  const std::string&			name,
862 													  const std::string&			desc,
863 													  const TextureLookupSpec&		lookup,
864 													  const TextureSpec&			texture,
865 													  TexEvalFunc					evalFunc,
866 													  bool							isVertexCase)
867 	: ShaderRenderCase		(testCtx, name, desc, isVertexCase, new TexLookupEvaluator(evalFunc, m_lookupParams), NULL, NULL)
868 	, m_lookupSpec			(lookup)
869 	, m_textureSpec			(texture)
870 {
871 	initShaderSources();
872 }
873 
~ShaderTextureFunctionCase(void)874 ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void)
875 {
876 }
877 
createInstance(Context & context) const878 TestInstance* ShaderTextureFunctionCase::createInstance (Context& context) const
879 {
880 	DE_ASSERT(m_evaluator != DE_NULL);
881 	DE_ASSERT(m_uniformSetup != DE_NULL);
882 	return new ShaderTextureFunctionInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_lookupSpec, m_textureSpec, m_lookupParams);
883 }
884 
initShaderSources(void)885 void ShaderTextureFunctionCase::initShaderSources (void)
886 {
887 	Function			function			= m_lookupSpec.function;
888 	bool				isVtxCase			= m_isVertexCase;
889 	bool				isProj				= functionHasProj(function);
890 	bool				isGrad				= functionHasGrad(function);
891 	bool				isShadow			= m_textureSpec.sampler.compare != tcu::Sampler::COMPAREMODE_NONE;
892 	bool				is2DProj4			= !isShadow && m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD || function == FUNCTION_TEXTUREPROJGRAD);
893 	bool				isIntCoord			= function == FUNCTION_TEXELFETCH;
894 	bool				hasLodBias			= functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias;
895 	int					texCoordComps		= m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3;
896 	int					extraCoordComps		= (isProj ? (is2DProj4 ? 2 : 1) : 0) + (isShadow ? 1 : 0);
897 	glu::DataType		coordType			= glu::getDataTypeFloatVec(texCoordComps+extraCoordComps);
898 	glu::Precision		coordPrec			= glu::PRECISION_HIGHP;
899 	const char*			coordTypeName		= glu::getDataTypeName(coordType);
900 	const char*			coordPrecName		= glu::getPrecisionName(coordPrec);
901 	tcu::TextureFormat	texFmt				= glu::mapGLInternalFormat(m_textureSpec.format);
902 	glu::DataType		samplerType			= glu::TYPE_LAST;
903 	glu::DataType		gradType			= (m_textureSpec.type == TEXTURETYPE_CUBE_MAP || m_textureSpec.type == TEXTURETYPE_3D) ? glu::TYPE_FLOAT_VEC3 : glu::TYPE_FLOAT_VEC2;
904 	const char*			gradTypeName		= glu::getDataTypeName(gradType);
905 	const char*			baseFuncName		= DE_NULL;
906 
907 	DE_ASSERT(!isGrad || !hasLodBias);
908 
909 	switch (m_textureSpec.type)
910 	{
911 		case TEXTURETYPE_2D:		samplerType = isShadow ? glu::TYPE_SAMPLER_2D_SHADOW		: glu::getSampler2DType(texFmt);		break;
912 		case TEXTURETYPE_CUBE_MAP:	samplerType = isShadow ? glu::TYPE_SAMPLER_CUBE_SHADOW		: glu::getSamplerCubeType(texFmt);		break;
913 		case TEXTURETYPE_2D_ARRAY:	samplerType = isShadow ? glu::TYPE_SAMPLER_2D_ARRAY_SHADOW	: glu::getSampler2DArrayType(texFmt);	break;
914 		case TEXTURETYPE_3D:		DE_ASSERT(!isShadow); samplerType = glu::getSampler3DType(texFmt);									break;
915 		default:
916 			DE_ASSERT(DE_FALSE);
917 	}
918 
919 	switch (m_lookupSpec.function)
920 	{
921 		case FUNCTION_TEXTURE:			baseFuncName = "texture";			break;
922 		case FUNCTION_TEXTUREPROJ:		baseFuncName = "textureProj";		break;
923 		case FUNCTION_TEXTUREPROJ3:		baseFuncName = "textureProj";		break;
924 		case FUNCTION_TEXTURELOD:		baseFuncName = "textureLod";		break;
925 		case FUNCTION_TEXTUREPROJLOD:	baseFuncName = "textureProjLod";	break;
926 		case FUNCTION_TEXTUREPROJLOD3:	baseFuncName = "textureProjLod";	break;
927 		case FUNCTION_TEXTUREGRAD:		baseFuncName = "textureGrad";		break;
928 		case FUNCTION_TEXTUREPROJGRAD:	baseFuncName = "textureProjGrad";	break;
929 		case FUNCTION_TEXTUREPROJGRAD3:	baseFuncName = "textureProjGrad";	break;
930 		case FUNCTION_TEXELFETCH:		baseFuncName = "texelFetch";		break;
931 		default:
932 			DE_ASSERT(DE_FALSE);
933 	}
934 
935 	std::ostringstream	vert;
936 	std::ostringstream	frag;
937 	std::ostringstream&	op		= isVtxCase ? vert : frag;
938 
939 	vert << "#version 310 es\n"
940 		 << "layout(location = 0) in highp vec4 a_position;\n"
941 		 << "layout(location = 4) in " << coordPrecName << " " << coordTypeName << " a_in0;\n";
942 
943 	if (isGrad)
944 	{
945 		vert << "layout(location = 5) in " << coordPrecName << " " << gradTypeName << " a_in1;\n";
946 		vert << "layout(location = 6) in " << coordPrecName << " " << gradTypeName << " a_in2;\n";
947 	}
948 	else if (hasLodBias)
949 		vert << "layout(location = 5) in " << coordPrecName << " float a_in1;\n";
950 
951 	frag << "#version 310 es\n"
952 		 << "layout(location = 0) out mediump vec4 o_color;\n";
953 
954 	if (isVtxCase)
955 	{
956 		vert << "layout(location = 0) out mediump vec4 v_color;\n";
957 		frag << "layout(location = 0) in mediump vec4 v_color;\n";
958 	}
959 	else
960 	{
961 		vert << "layout(location = 0) out " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
962 		frag << "layout(location = 0) in " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
963 
964 		if (isGrad)
965 		{
966 			vert << "layout(location = 1) out " << coordPrecName << " " << gradTypeName << " v_gradX;\n";
967 			vert << "layout(location = 2) out " << coordPrecName << " " << gradTypeName << " v_gradY;\n";
968 			frag << "layout(location = 1) in " << coordPrecName << " " << gradTypeName << " v_gradX;\n";
969 			frag << "layout(location = 2) in " << coordPrecName << " " << gradTypeName << " v_gradY;\n";
970 		}
971 		else if (hasLodBias)
972 		{
973 			vert << "layout(location = 1) out " << coordPrecName << " float v_lodBias;\n";
974 			frag << "layout(location = 1) in " << coordPrecName << " float v_lodBias;\n";
975 		}
976 	}
977 
978 	// Uniforms
979 	op << "layout(set = 0, binding = 0) uniform highp " << glu::getDataTypeName(samplerType) << " u_sampler;\n"
980 	   << "layout(set = 0, binding = 1) uniform buf0 { highp vec4 u_scale; };\n"
981 	   << "layout(set = 0, binding = 2) uniform buf1 { highp vec4 u_bias; };\n";
982 
983 	vert << "\nvoid main()\n{\n"
984 		 << "\tgl_Position = a_position;\n";
985 	frag << "\nvoid main()\n{\n";
986 
987 	if (isVtxCase)
988 		vert << "\tv_color = ";
989 	else
990 		frag << "\to_color = ";
991 
992 	// Op.
993 	{
994 		const char*	texCoord	= isVtxCase ? "a_in0" : "v_texCoord";
995 		const char* gradX		= isVtxCase ? "a_in1" : "v_gradX";
996 		const char* gradY		= isVtxCase ? "a_in2" : "v_gradY";
997 		const char*	lodBias		= isVtxCase ? "a_in1" : "v_lodBias";
998 
999 		op << "vec4(" << baseFuncName;
1000 		if (m_lookupSpec.useOffset)
1001 			op << "Offset";
1002 		op << "(u_sampler, ";
1003 
1004 		if (isIntCoord)
1005 			op << "ivec" << (texCoordComps+extraCoordComps) << "(";
1006 
1007 		op << texCoord;
1008 
1009 		if (isIntCoord)
1010 			op << ")";
1011 
1012 		if (isGrad)
1013 			op << ", " << gradX << ", " << gradY;
1014 
1015 		if (functionHasLod(function))
1016 		{
1017 			if (isIntCoord)
1018 				op << ", int(" << lodBias << ")";
1019 			else
1020 				op << ", " << lodBias;
1021 		}
1022 
1023 		if (m_lookupSpec.useOffset)
1024 		{
1025 			int offsetComps = m_textureSpec.type == TEXTURETYPE_3D ? 3 : 2;
1026 
1027 			op << ", ivec" << offsetComps << "(";
1028 			for (int ndx = 0; ndx < offsetComps; ndx++)
1029 			{
1030 				if (ndx != 0)
1031 					op << ", ";
1032 				op << m_lookupSpec.offset[ndx];
1033 			}
1034 			op << ")";
1035 		}
1036 
1037 		if (m_lookupSpec.useBias)
1038 			op << ", " << lodBias;
1039 
1040 		op << ")";
1041 
1042 		if (isShadow)
1043 			op << ", 0.0, 0.0, 1.0)";
1044 		else
1045 			op << ")*u_scale + u_bias";
1046 
1047 		op << ";\n";
1048 	}
1049 
1050 	if (isVtxCase)
1051 		frag << "\to_color = v_color;\n";
1052 	else
1053 	{
1054 		vert << "\tv_texCoord = a_in0;\n";
1055 
1056 		if (isGrad)
1057 		{
1058 			vert << "\tv_gradX = a_in1;\n";
1059 			vert << "\tv_gradY = a_in2;\n";
1060 		}
1061 		else if (hasLodBias)
1062 			vert << "\tv_lodBias = a_in1;\n";
1063 	}
1064 
1065 	vert << "}\n";
1066 	frag << "}\n";
1067 
1068 	m_vertShaderSource = vert.str();
1069 	m_fragShaderSource = frag.str();
1070 }
1071 
1072 enum QueryFunction
1073 {
1074 	QUERYFUNCTION_TEXTURESIZE = 0,
1075 	QUERYFUNCTION_TEXTUREQUERYLOD,
1076 	QUERYFUNCTION_TEXTUREQUERYLEVELS,
1077 	QUERYFUNCTION_TEXTURESAMPLES,
1078 
1079 	QUERYFUNCTION_LAST
1080 };
1081 
checkDeviceFeatures(Context & context,TextureType textureType)1082 static void checkDeviceFeatures (Context& context, TextureType textureType)
1083 {
1084 	if (textureType == TEXTURETYPE_CUBE_ARRAY)
1085 	{
1086 		const vk::VkPhysicalDeviceFeatures&	deviceFeatures	= context.getDeviceFeatures();
1087 
1088 		if (!deviceFeatures.imageCubeArray)
1089 			TCU_THROW(NotSupportedError, "Cube array is not supported");
1090 	}
1091 }
1092 
1093 class TextureQueryInstance : public ShaderRenderCaseInstance
1094 {
1095 public:
1096 								TextureQueryInstance			(Context&					context,
1097 																 const bool					isVertexCase,
1098 																 const TextureSpec&			textureSpec);
1099 	virtual						~TextureQueryInstance			(void);
1100 
1101 protected:
1102 	virtual void				setupDefaultInputs				(void);
1103 	virtual void				setupUniforms					(const tcu::Vec4&);
1104 
1105 	void						render							(void);
1106 
1107 protected:
1108 	const TextureSpec&			m_textureSpec;
1109 };
1110 
TextureQueryInstance(Context & context,const bool isVertexCase,const TextureSpec & textureSpec)1111 TextureQueryInstance::TextureQueryInstance (Context&				context,
1112 											const bool				isVertexCase,
1113 											const TextureSpec&		textureSpec)
1114 	: ShaderRenderCaseInstance	(context, isVertexCase, DE_NULL, DE_NULL, DE_NULL)
1115 	, m_textureSpec				(textureSpec)
1116 {
1117 	m_colorFormat = vk::VK_FORMAT_R32G32B32A32_SFLOAT;
1118 
1119 	checkDeviceFeatures(m_context, m_textureSpec.type);
1120 }
1121 
~TextureQueryInstance(void)1122 TextureQueryInstance::~TextureQueryInstance (void)
1123 {
1124 }
1125 
setupDefaultInputs(void)1126 void TextureQueryInstance::setupDefaultInputs (void)
1127 {
1128 	const deUint32		numVertices		= 4;
1129 	const float			positions[]		=
1130 	{
1131 		-1.0f, -1.0f, 0.0f, 1.0f,
1132 		-1.0f,  1.0f, 0.0f, 1.0f,
1133 		 1.0f, -1.0f, 0.0f, 1.0f,
1134 		 1.0f,  1.0f, 0.0f, 1.0f
1135 	};
1136 
1137 	addAttribute(0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 4 * (deUint32)sizeof(float), numVertices, positions);
1138 }
1139 
setupUniforms(const tcu::Vec4 &)1140 void TextureQueryInstance::setupUniforms (const tcu::Vec4&)
1141 {
1142 	useSampler(0u, 0u);
1143 }
1144 
render(void)1145 void TextureQueryInstance::render (void)
1146 {
1147 	const deUint32		numVertices		= 4;
1148 	const deUint32		numTriangles	= 2;
1149 	const deUint16		indices[6]		= { 0, 1, 2, 2, 1, 3 };
1150 
1151 	ShaderRenderCaseInstance::setup();
1152 
1153 	ShaderRenderCaseInstance::render(numVertices, numTriangles, indices);
1154 }
1155 
getMaxTextureSize(TextureType type,const tcu::IVec3 & textureSize)1156 static int getMaxTextureSize (TextureType type, const tcu::IVec3& textureSize)
1157 {
1158 	int		maxSize		= 0;
1159 
1160 	switch (type)
1161 	{
1162 		case TEXTURETYPE_1D:
1163 		case TEXTURETYPE_1D_ARRAY:
1164 			maxSize = textureSize.x();
1165 			break;
1166 
1167 		case TEXTURETYPE_2D:
1168 		case TEXTURETYPE_2D_ARRAY:
1169 		case TEXTURETYPE_CUBE_MAP:
1170 		case TEXTURETYPE_CUBE_ARRAY:
1171 			maxSize = de::max(textureSize.x(), textureSize.y());
1172 			break;
1173 
1174 		case TEXTURETYPE_3D:
1175 			maxSize = de::max(textureSize.x(), de::max(textureSize.y(), textureSize.z()));
1176 			break;
1177 
1178 		default:
1179 			DE_ASSERT(false);
1180 	}
1181 
1182 	return maxSize;
1183 }
1184 
getTextureSizeString(TextureType type,const tcu::IVec3 & textureSize)1185 static std::string getTextureSizeString (TextureType type, const tcu::IVec3& textureSize)
1186 {
1187 	std::ostringstream	str;
1188 
1189 	switch (type)
1190 	{
1191 		case TEXTURETYPE_1D:
1192 			str << textureSize.x() << "x1";
1193 			break;
1194 
1195 		case TEXTURETYPE_2D:
1196 		case TEXTURETYPE_CUBE_MAP:
1197 			str << textureSize.x() << "x" << textureSize.y();
1198 			break;
1199 
1200 		case TEXTURETYPE_3D:
1201 			str << textureSize.x() << "x" << textureSize.y() << "x" << textureSize.z();
1202 			break;
1203 
1204 		case TEXTURETYPE_1D_ARRAY:
1205 			str << textureSize.x() << "x1 with " << textureSize.z() << " layer(s)";
1206 			break;
1207 
1208 		case TEXTURETYPE_2D_ARRAY:
1209 		case TEXTURETYPE_CUBE_ARRAY:
1210 			str << textureSize.x() << "x" << textureSize.y() << " with " << textureSize.z() << " layers(s)";
1211 			break;
1212 
1213 		default:
1214 			DE_ASSERT(false);
1215 			break;
1216 	}
1217 
1218 	return str.str();
1219 }
1220 
isValidCase(TextureType type,const tcu::IVec3 & textureSize,int lod,int lodBase)1221 static bool isValidCase (TextureType type, const tcu::IVec3& textureSize, int lod, int lodBase)
1222 {
1223 	const bool		isSquare		= textureSize.x() == textureSize.y();
1224 	const bool		isCubeArray		= isSquare && (textureSize.z() % 6) == 0;
1225 	const int		maxSize			= getMaxTextureSize(type, textureSize);
1226 	const bool		isLodValid		= (maxSize >> (lod + lodBase)) != 0;
1227 
1228 	if (!isLodValid)
1229 		return false;
1230 	if (type == TEXTURETYPE_CUBE_MAP && !isSquare)
1231 		return false;
1232 	if (type == TEXTURETYPE_CUBE_ARRAY && !isCubeArray)
1233 		return false;
1234 
1235 	return true;
1236 }
1237 
createEmptyTexture(deUint32 format,TextureType type,const tcu::IVec3 & textureSize,int numLevels,int lodBase,const tcu::Sampler & sampler)1238 static TextureBindingSp createEmptyTexture (deUint32				format,
1239 											TextureType				type,
1240 											const tcu::IVec3&		textureSize,
1241 											int						numLevels,
1242 											int						lodBase,
1243 											const tcu::Sampler&		sampler)
1244 {
1245 	const tcu::TextureFormat			texFmt				= glu::mapGLInternalFormat(format);
1246 	const TextureBinding::Parameters	params				(lodBase);
1247 	TextureBindingSp					textureBinding;
1248 
1249 	switch (type)
1250 	{
1251 
1252 		case TEXTURETYPE_1D:
1253 		{
1254 			de::MovePtr<tcu::Texture1D>			texture		(new tcu::Texture1D(texFmt, textureSize.x()));
1255 
1256 			for (int level = 0; level < numLevels; level++)
1257 				texture->allocLevel(level);
1258 
1259 			textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler));
1260 			break;
1261 		}
1262 
1263 		case TEXTURETYPE_2D:
1264 		{
1265 			de::MovePtr<tcu::Texture2D>			texture		(new tcu::Texture2D(texFmt, textureSize.x(), textureSize.y()));
1266 
1267 			for (int level = 0; level < numLevels; level++)
1268 				texture->allocLevel(level);
1269 
1270 			textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler));
1271 			break;
1272 		}
1273 
1274 		case TEXTURETYPE_3D:
1275 		{
1276 			de::MovePtr<tcu::Texture3D>			texture		(new tcu::Texture3D(texFmt, textureSize.x(), textureSize.y(), textureSize.z()));
1277 
1278 			for (int level = 0; level < numLevels; level++)
1279 				texture->allocLevel(level);
1280 
1281 			textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler));
1282 			break;
1283 		}
1284 
1285 		case TEXTURETYPE_CUBE_MAP:
1286 		{
1287 			de::MovePtr<tcu::TextureCube>		texture		(new tcu::TextureCube(texFmt, textureSize.x()));
1288 
1289 			for (int level = 0; level < numLevels; level++)
1290 				for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1291 					texture->allocLevel((tcu::CubeFace)face, level);
1292 
1293 			textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler));
1294 			break;
1295 		}
1296 
1297 		case TEXTURETYPE_1D_ARRAY:
1298 		{
1299 			de::MovePtr<tcu::Texture1DArray>	texture		(new tcu::Texture1DArray(texFmt, textureSize.x(), textureSize.z()));
1300 
1301 			for (int level = 0; level < numLevels; level++)
1302 				texture->allocLevel(level);
1303 
1304 			textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler));
1305 			break;
1306 		}
1307 
1308 		case TEXTURETYPE_2D_ARRAY:
1309 		{
1310 			de::MovePtr<tcu::Texture2DArray>	texture		(new tcu::Texture2DArray(texFmt, textureSize.x(), textureSize.y(), textureSize.z()));
1311 
1312 			for (int level = 0; level < numLevels; level++)
1313 				texture->allocLevel(level);
1314 
1315 			textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler));
1316 			break;
1317 		}
1318 
1319 		case TEXTURETYPE_CUBE_ARRAY:
1320 		{
1321 			de::MovePtr<tcu::TextureCubeArray>	texture		(new tcu::TextureCubeArray(texFmt, textureSize.x(), textureSize.z()));
1322 
1323 			for (int level = 0; level < numLevels; level++)
1324 				texture->allocLevel(level);
1325 
1326 			textureBinding = TextureBindingSp(new TextureBinding(texture.release(), sampler));
1327 			break;
1328 		}
1329 
1330 		default:
1331 			DE_ASSERT(false);
1332 			break;
1333 	}
1334 
1335 	textureBinding->setParameters(params);
1336 	return textureBinding;
1337 }
1338 
getTextureSizeFuncResultType(TextureType textureType)1339 static inline glu::DataType getTextureSizeFuncResultType (TextureType textureType)
1340 {
1341 	switch (textureType)
1342 	{
1343 		case TEXTURETYPE_1D:
1344 			return glu::TYPE_INT;
1345 
1346 		case TEXTURETYPE_2D:
1347 		case TEXTURETYPE_CUBE_MAP:
1348 		case TEXTURETYPE_1D_ARRAY:
1349 			return glu::TYPE_INT_VEC2;
1350 
1351 		case TEXTURETYPE_3D:
1352 		case TEXTURETYPE_2D_ARRAY:
1353 		case TEXTURETYPE_CUBE_ARRAY:
1354 			return glu::TYPE_INT_VEC3;
1355 
1356 		default:
1357 			DE_ASSERT(false);
1358 			return glu::TYPE_LAST;
1359 	}
1360 }
1361 
1362 class TextureSizeInstance : public TextureQueryInstance
1363 {
1364 public:
1365 								TextureSizeInstance				(Context&					context,
1366 																 const bool					isVertexCase,
1367 																 const TextureSpec&			textureSpec);
1368 	virtual						~TextureSizeInstance			(void);
1369 
1370 	virtual tcu::TestStatus		iterate							(void);
1371 
1372 protected:
1373 	virtual void				setupUniforms					(const tcu::Vec4& constCoords);
1374 
1375 private:
1376 	struct TestSize
1377 	{
1378 		tcu::IVec3	textureSize;
1379 		int			lod;
1380 		int			lodBase;
1381 		tcu::IVec3	expectedSize;
1382 	};
1383 
1384 	void						initTexture						(void);
1385 	bool						testTextureSize					(void);
1386 
1387 	TestSize					m_testSize;
1388 	tcu::IVec3					m_expectedSize;
1389 	int							m_iterationCounter;
1390 };
1391 
TextureSizeInstance(Context & context,const bool isVertexCase,const TextureSpec & textureSpec)1392 TextureSizeInstance::TextureSizeInstance (Context&					context,
1393 										  const bool				isVertexCase,
1394 										  const TextureSpec&		textureSpec)
1395 	: TextureQueryInstance		(context, isVertexCase, textureSpec)
1396 	, m_testSize				()
1397 	, m_expectedSize			()
1398 	, m_iterationCounter		(0)
1399 {
1400 	deMemset(&m_testSize, 0, sizeof(TestSize));
1401 
1402 	m_renderSize = tcu::UVec2(1, 1);
1403 }
1404 
~TextureSizeInstance(void)1405 TextureSizeInstance::~TextureSizeInstance (void)
1406 {
1407 }
1408 
setupUniforms(const tcu::Vec4 & constCoords)1409 void TextureSizeInstance::setupUniforms (const tcu::Vec4& constCoords)
1410 {
1411 	TextureQueryInstance::setupUniforms(constCoords);
1412 	addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(int), &m_testSize.lod);
1413 }
1414 
initTexture(void)1415 void TextureSizeInstance::initTexture (void)
1416 {
1417 	tcu::TestLog&			log					= m_context.getTestContext().getLog();
1418 	const int				numLevels			= m_testSize.lod + m_testSize.lodBase + 1;
1419 	TextureBindingSp		textureBinding;
1420 
1421 	log << tcu::TestLog::Message << "Testing image size " << getTextureSizeString(m_textureSpec.type, m_testSize.textureSize) << tcu::TestLog::EndMessage;
1422 	log << tcu::TestLog::Message << "Lod: " << m_testSize.lod << ", base level: " << m_testSize.lodBase << tcu::TestLog::EndMessage;
1423 
1424 	switch (m_textureSpec.type)
1425 	{
1426 		case TEXTURETYPE_3D:
1427 			log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << "x" << m_testSize.expectedSize.z() << tcu::TestLog::EndMessage;
1428 			break;
1429 
1430 		case TEXTURETYPE_2D:
1431 			log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << tcu::TestLog::EndMessage;
1432 			break;
1433 
1434 		case TEXTURETYPE_CUBE_MAP:
1435 			log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << tcu::TestLog::EndMessage;
1436 			break;
1437 
1438 		case TEXTURETYPE_2D_ARRAY:
1439 			log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << " and " << m_testSize.textureSize.z() << " layer(s)" << tcu::TestLog::EndMessage;
1440 			break;
1441 
1442 		case TEXTURETYPE_CUBE_ARRAY:
1443 			log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << "x" << m_testSize.expectedSize.y() << " and " << (m_testSize.textureSize.z() / 6) << " cube(s)" << tcu::TestLog::EndMessage;
1444 			break;
1445 
1446 		case TEXTURETYPE_1D:
1447 			log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << tcu::TestLog::EndMessage;
1448 			break;
1449 
1450 		case TEXTURETYPE_1D_ARRAY:
1451 			log << tcu::TestLog::Message << "Expecting: " << m_testSize.expectedSize.x() << " and " << m_testSize.textureSize.z() << " layer(s)" << tcu::TestLog::EndMessage;
1452 			break;
1453 
1454 		default:
1455 			DE_ASSERT(false);
1456 			break;
1457 	}
1458 
1459 	textureBinding = createEmptyTexture(m_textureSpec.format, m_textureSpec.type, m_testSize.textureSize, numLevels, m_testSize.lodBase, m_textureSpec.sampler);
1460 
1461 	m_textures.clear();
1462 	m_textures.push_back(textureBinding);
1463 }
1464 
iterate(void)1465 tcu::TestStatus TextureSizeInstance::iterate (void)
1466 {
1467 	const TestSize testSizes[] =
1468 	{
1469 		{ tcu::IVec3(1, 2, 1),			0,		0,	tcu::IVec3(1, 2, 1)			},
1470 		{ tcu::IVec3(1, 2, 1),			1,		0,	tcu::IVec3(1, 1, 1)			},
1471 
1472 		{ tcu::IVec3(1, 3, 2),			0,		0,	tcu::IVec3(1, 3, 2)			},
1473 		{ tcu::IVec3(1, 3, 2),			1,		0,	tcu::IVec3(1, 1, 1)			},
1474 
1475 		{ tcu::IVec3(100, 31, 18),		0,		0,	tcu::IVec3(100, 31, 18)		},
1476 		{ tcu::IVec3(100, 31, 18),		1,		0,	tcu::IVec3(50, 15, 9)		},
1477 		{ tcu::IVec3(100, 31, 18),		2,		0,	tcu::IVec3(25, 7, 4)		},
1478 		{ tcu::IVec3(100, 31, 18),		3,		0,	tcu::IVec3(12, 3, 2)		},
1479 		{ tcu::IVec3(100, 31, 18),		4,		0,	tcu::IVec3(6, 1, 1)			},
1480 		{ tcu::IVec3(100, 31, 18),		5,		0,	tcu::IVec3(3, 1, 1)			},
1481 		{ tcu::IVec3(100, 31, 18),		6,		0,	tcu::IVec3(1, 1, 1)			},
1482 
1483 		{ tcu::IVec3(100, 128, 32),		0,		0,	tcu::IVec3(100, 128, 32)	},
1484 		{ tcu::IVec3(100, 128, 32),		1,		0,	tcu::IVec3(50, 64, 16)		},
1485 		{ tcu::IVec3(100, 128, 32),		2,		0,	tcu::IVec3(25, 32, 8)		},
1486 		{ tcu::IVec3(100, 128, 32),		3,		0,	tcu::IVec3(12, 16, 4)		},
1487 		{ tcu::IVec3(100, 128, 32),		4,		0,	tcu::IVec3(6, 8, 2)			},
1488 		{ tcu::IVec3(100, 128, 32),		5,		0,	tcu::IVec3(3, 4, 1)			},
1489 		{ tcu::IVec3(100, 128, 32),		6,		0,	tcu::IVec3(1, 2, 1)			},
1490 		{ tcu::IVec3(100, 128, 32),		7,		0,	tcu::IVec3(1, 1, 1)			},
1491 
1492 		// pow 2
1493 		{ tcu::IVec3(128, 64, 32),		0,		0,	tcu::IVec3(128, 64, 32)		},
1494 		{ tcu::IVec3(128, 64, 32),		1,		0,	tcu::IVec3(64, 32, 16)		},
1495 		{ tcu::IVec3(128, 64, 32),		2,		0,	tcu::IVec3(32, 16, 8)		},
1496 		{ tcu::IVec3(128, 64, 32),		3,		0,	tcu::IVec3(16, 8, 4)		},
1497 		{ tcu::IVec3(128, 64, 32),		4,		0,	tcu::IVec3(8, 4, 2)			},
1498 		{ tcu::IVec3(128, 64, 32),		5,		0,	tcu::IVec3(4, 2, 1)			},
1499 		{ tcu::IVec3(128, 64, 32),		6,		0,	tcu::IVec3(2, 1, 1)			},
1500 		{ tcu::IVec3(128, 64, 32),		7,		0,	tcu::IVec3(1, 1, 1)			},
1501 
1502 		// w == h
1503 		{ tcu::IVec3(1, 1, 1),			0,		0,	tcu::IVec3(1, 1, 1)			},
1504 		{ tcu::IVec3(64, 64, 64),		0,		0,	tcu::IVec3(64, 64, 64)		},
1505 		{ tcu::IVec3(64, 64, 64),		1,		0,	tcu::IVec3(32, 32, 32)		},
1506 		{ tcu::IVec3(64, 64, 64),		2,		0,	tcu::IVec3(16, 16, 16)		},
1507 		{ tcu::IVec3(64, 64, 64),		3,		0,	tcu::IVec3(8, 8, 8)			},
1508 		{ tcu::IVec3(64, 64, 64),		4,		0,	tcu::IVec3(4, 4, 4)			},
1509 
1510 		// with lod base
1511 		{ tcu::IVec3(100, 31, 18),		3,		1,	tcu::IVec3(6, 1, 1)			},
1512 		{ tcu::IVec3(128, 64, 32),		3,		1,	tcu::IVec3(8, 4, 2)			},
1513 		{ tcu::IVec3(64, 64, 64),		1,		1,	tcu::IVec3(16, 16, 16)		},
1514 
1515 		// w == h and d % 6 == 0 (for cube array)
1516 		{ tcu::IVec3(1, 1, 6),			0,		0,	tcu::IVec3(1, 1, 6)			},
1517 		{ tcu::IVec3(32, 32, 12),		0,		0,	tcu::IVec3(32, 32, 12)		},
1518 		{ tcu::IVec3(32, 32, 12),		0,		1,	tcu::IVec3(16, 16, 6)		},
1519 		{ tcu::IVec3(32, 32, 12),		1,		0,	tcu::IVec3(16, 16, 6)		},
1520 		{ tcu::IVec3(32, 32, 12),		2,		0,	tcu::IVec3(8, 8, 3)			},
1521 		{ tcu::IVec3(32, 32, 12),		3,		0,	tcu::IVec3(4, 4, 1)			},
1522 		{ tcu::IVec3(32, 32, 12),		4,		0,	tcu::IVec3(2, 2, 1)			},
1523 		{ tcu::IVec3(32, 32, 12),		5,		0,	tcu::IVec3(1, 1, 1)			},
1524 	};
1525 	const int lastIterationIndex = DE_LENGTH_OF_ARRAY(testSizes) + 1;
1526 
1527 	m_iterationCounter++;
1528 
1529 	if (m_iterationCounter == lastIterationIndex)
1530 		return tcu::TestStatus::pass("Pass");
1531 	else
1532 	{
1533 		// set current test size
1534 		m_testSize = testSizes[m_iterationCounter - 1];
1535 
1536 		if (!testTextureSize())
1537 			return tcu::TestStatus::fail("Got unexpected result");
1538 
1539 		return tcu::TestStatus::incomplete();
1540 	}
1541 }
1542 
testTextureSize(void)1543 bool TextureSizeInstance::testTextureSize (void)
1544 {
1545 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
1546 	bool					success			= true;
1547 
1548 	// skip incompatible cases
1549 	if (!isValidCase(m_textureSpec.type, m_testSize.textureSize, m_testSize.lod, m_testSize.lodBase))
1550 		return true;
1551 
1552 	// setup texture
1553 	initTexture();
1554 
1555 	// determine expected texture size
1556 	switch (m_textureSpec.type)
1557 	{
1558 		case TEXTURETYPE_1D:
1559 		case TEXTURETYPE_2D:
1560 		case TEXTURETYPE_3D:
1561 		case TEXTURETYPE_CUBE_MAP:
1562 			m_expectedSize = m_testSize.expectedSize;
1563 			break;
1564 
1565 		case TEXTURETYPE_1D_ARRAY:
1566 			m_expectedSize = tcu::IVec3(m_testSize.expectedSize.x(), m_testSize.textureSize.z(), 0);
1567 			break;
1568 
1569 		case TEXTURETYPE_2D_ARRAY:
1570 			m_expectedSize = tcu::IVec3(m_testSize.expectedSize.x(), m_testSize.expectedSize.y(), m_testSize.textureSize.z());
1571 			break;
1572 
1573 		case TEXTURETYPE_CUBE_ARRAY:
1574 			m_expectedSize = tcu::IVec3(m_testSize.expectedSize.x(), m_testSize.expectedSize.y(), m_testSize.textureSize.z() / 6);
1575 			break;
1576 
1577 		default:
1578 			DE_ASSERT(false);
1579 			break;
1580 	}
1581 
1582 	// render
1583 	TextureQueryInstance::render();
1584 
1585 	// test
1586 	{
1587 		const tcu::TextureLevel&	result				= getResultImage();
1588 		tcu::IVec4					output				= result.getAccess().getPixelInt(0, 0);
1589 		const int					resultComponents	= glu::getDataTypeScalarSize(getTextureSizeFuncResultType(m_textureSpec.type));
1590 
1591 		for (int ndx = 0; ndx < resultComponents; ndx++)
1592 		{
1593 			if (output[ndx] != m_expectedSize[ndx])
1594 			{
1595 				success = false;
1596 				break;
1597 			}
1598 		}
1599 
1600 		if (success)
1601 		{
1602 			// success
1603 			log << tcu::TestLog::Message << "Passed" << tcu::TestLog::EndMessage;
1604 		}
1605 		else
1606 		{
1607 			// failure
1608 			std::stringstream	resultSizeStr;
1609 			switch (resultComponents)
1610 			{
1611 				case 1:
1612 					resultSizeStr << output[0];
1613 					break;
1614 				case 2:
1615 					resultSizeStr << output.toWidth<2>();
1616 					break;
1617 				case 3:
1618 					resultSizeStr << output.toWidth<3>();
1619 					break;
1620 				default:
1621 					DE_ASSERT(false);
1622 					break;
1623 			}
1624 			log << tcu::TestLog::Message << "Result: " << resultSizeStr.str() << tcu::TestLog::EndMessage;
1625 			log << tcu::TestLog::Message << "Failed" << tcu::TestLog::EndMessage;
1626 		}
1627 	}
1628 
1629 	log << tcu::TestLog::Message << tcu::TestLog::EndMessage;
1630 
1631 	return success;
1632 }
1633 
getVkImageType(TextureType type)1634 static vk::VkImageType getVkImageType (TextureType type)
1635 {
1636 	switch (type)
1637 	{
1638 		case TEXTURETYPE_1D:
1639 		case TEXTURETYPE_1D_ARRAY:
1640 			return vk::VK_IMAGE_TYPE_1D;
1641 
1642 		case TEXTURETYPE_2D:
1643 		case TEXTURETYPE_2D_ARRAY:
1644 		case TEXTURETYPE_CUBE_MAP:
1645 		case TEXTURETYPE_CUBE_ARRAY:
1646 			return vk::VK_IMAGE_TYPE_2D;
1647 
1648 		case TEXTURETYPE_3D:
1649 			return vk::VK_IMAGE_TYPE_3D;
1650 
1651 		default:
1652 			DE_ASSERT(false);
1653 			return (vk::VkImageType)0;
1654 	}
1655 }
1656 
1657 class TextureSamplesInstance : public TextureQueryInstance
1658 {
1659 public:
1660 								TextureSamplesInstance			(Context&					context,
1661 																 const bool					isVertexCase,
1662 																 const TextureSpec&			textureSpec);
1663 	virtual						~TextureSamplesInstance			(void);
1664 
1665 	virtual tcu::TestStatus		iterate							(void);
1666 
1667 private:
1668 	void						initTexture						(void);
1669 
1670 	int										m_iterationCounter;
1671 	vector<vk::VkSampleCountFlagBits>		m_iterations;
1672 };
1673 
TextureSamplesInstance(Context & context,const bool isVertexCase,const TextureSpec & textureSpec)1674 TextureSamplesInstance::TextureSamplesInstance (Context&				context,
1675 												const bool				isVertexCase,
1676 												const TextureSpec&		textureSpec)
1677 	: TextureQueryInstance		(context, isVertexCase, textureSpec)
1678 	, m_iterationCounter		(0)
1679 {
1680 	m_renderSize = tcu::UVec2(1, 1);
1681 
1682 	// determine available sample counts
1683 	{
1684 		const vk::VkFormat						format			= vk::mapTextureFormat(glu::mapGLInternalFormat(m_textureSpec.format));
1685 		const vk::VkImageType					imageType		= getVkImageType(m_textureSpec.type);
1686 		vk::VkImageFormatProperties				properties;
1687 
1688 		if (m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
1689 																					format,
1690 																					imageType,
1691 																					vk::VK_IMAGE_TILING_OPTIMAL,
1692 																					vk::VK_IMAGE_USAGE_SAMPLED_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
1693 																					(vk::VkImageCreateFlags)0,
1694 																					&properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1695 			TCU_THROW(NotSupportedError, "Format not supported");
1696 
1697 		// NOTE: The test case initializes MS images (for all supported N of samples), runs a program
1698 		//       which invokes OpImageQuerySamples against the image and checks the result.
1699 		//
1700 		//       Now, in the SPIR-V spec for the very operation we have the following language:
1701 		//
1702 		//       OpImageQuerySamples
1703 		//       Query the number of samples available per texel fetch in a multisample image.
1704 		//       Result Type must be a scalar integer type.
1705 		//       The result is the number of samples.
1706 		//       Image must be an object whose type is OpTypeImage.
1707 		//       Its Dim operand must be one of 2D and **MS of 1(multisampled).
1708 		//
1709 		//       "MS of 1" implies the image must not be single-sample, meaning we must exclude
1710 		//       VK_SAMPLE_COUNT_1_BIT in the sampleFlags array below, and may have to skip further testing.
1711 		static const vk::VkSampleCountFlagBits	sampleFlags[]	=
1712 		{
1713 			vk::VK_SAMPLE_COUNT_2_BIT,
1714 			vk::VK_SAMPLE_COUNT_4_BIT,
1715 			vk::VK_SAMPLE_COUNT_8_BIT,
1716 			vk::VK_SAMPLE_COUNT_16_BIT,
1717 			vk::VK_SAMPLE_COUNT_32_BIT,
1718 			vk::VK_SAMPLE_COUNT_64_BIT
1719 		};
1720 
1721 		for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(sampleFlags); samplesNdx++)
1722 		{
1723 			const vk::VkSampleCountFlagBits&	flag			= sampleFlags[samplesNdx];
1724 
1725 			if ((properties.sampleCounts & flag) != 0)
1726 				m_iterations.push_back(flag);
1727 		}
1728 
1729 		if (m_iterations.empty())
1730 		{
1731 			// Sampled images of integer formats may support only 1 sample. Exit the test with "Not supported" in these cases.
1732 			if (tcu::getTextureChannelClass(mapVkFormat(format).type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ||
1733 				tcu::getTextureChannelClass(mapVkFormat(format).type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1734 			{
1735 				TCU_THROW(NotSupportedError, "Skipping validation of integer formats as only VK_SAMPLE_COUNT_1_BIT is supported.");
1736 			}
1737 
1738 			DE_ASSERT(false);
1739 		}
1740 	}
1741 
1742 	// setup texture
1743 	initTexture();
1744 }
1745 
~TextureSamplesInstance(void)1746 TextureSamplesInstance::~TextureSamplesInstance (void)
1747 {
1748 }
1749 
iterate(void)1750 tcu::TestStatus TextureSamplesInstance::iterate (void)
1751 {
1752 	tcu::TestLog&		log		= m_context.getTestContext().getLog();
1753 
1754 	// update samples count
1755 	{
1756 		DE_ASSERT(m_textures.size() == 1);
1757 
1758 		TextureBinding::Parameters	params	= m_textures[0]->getParameters();
1759 
1760 		params.initialization	= TextureBinding::INIT_CLEAR;
1761 		params.samples			= m_iterations[m_iterationCounter];
1762 		log << tcu::TestLog::Message << "Expected samples: " << m_iterations[m_iterationCounter] << tcu::TestLog::EndMessage;
1763 
1764 		m_textures[0]->setParameters(params);
1765 	}
1766 
1767 	// render
1768 	TextureQueryInstance::render();
1769 
1770 	// test
1771 	{
1772 		const tcu::TextureLevel&	result				= getResultImage();
1773 		tcu::IVec4					output				= result.getAccess().getPixelInt(0, 0);
1774 
1775 		if (output.x() == (int)m_iterations[m_iterationCounter])
1776 		{
1777 			// success
1778 			log << tcu::TestLog::Message << "Passed" << tcu::TestLog::EndMessage;
1779 		}
1780 		else
1781 		{
1782 			// failure
1783 			log << tcu::TestLog::Message << "Result: " << output.x() << tcu::TestLog::EndMessage;
1784 			log << tcu::TestLog::Message << "Failed" << tcu::TestLog::EndMessage;
1785 			return tcu::TestStatus::fail("Got unexpected result");
1786 		}
1787 
1788 		m_iterationCounter++;
1789 		if (m_iterationCounter == (int)m_iterations.size())
1790 			return tcu::TestStatus::pass("Pass");
1791 		else
1792 			return tcu::TestStatus::incomplete();
1793 	}
1794 }
1795 
initTexture(void)1796 void TextureSamplesInstance::initTexture (void)
1797 {
1798 	tcu::TestLog&			log					= m_context.getTestContext().getLog();
1799 	tcu::IVec3				textureSize			(m_textureSpec.width, m_textureSpec.height, m_textureSpec.depth);
1800 	TextureBindingSp		textureBinding;
1801 
1802 	DE_ASSERT(m_textures.empty());
1803 	DE_ASSERT(m_textureSpec.type == TEXTURETYPE_2D || m_textureSpec.type == TEXTURETYPE_2D_ARRAY);
1804 
1805 	log << tcu::TestLog::Message << "Image size: " << getTextureSizeString(m_textureSpec.type, textureSize) << tcu::TestLog::EndMessage;
1806 
1807 	textureBinding = createEmptyTexture(m_textureSpec.format, m_textureSpec.type, textureSize, m_textureSpec.numLevels, 0 /* lodBase */, m_textureSpec.sampler);
1808 
1809 	m_textures.push_back(textureBinding);
1810 }
1811 
1812 class TextureQueryLevelsInstance : public TextureQueryInstance
1813 {
1814 public:
1815 								TextureQueryLevelsInstance		(Context&					context,
1816 																 const bool					isVertexCase,
1817 																 const TextureSpec&			textureSpec);
1818 	virtual						~TextureQueryLevelsInstance		(void);
1819 
1820 	virtual tcu::TestStatus		iterate							(void);
1821 
1822 private:
1823 	struct TestSize
1824 	{
1825 		tcu::IVec3	textureSize;
1826 		int			lodBase;
1827 	};
1828 
1829 	void						initTexture						(void);
1830 	bool						testTextureLevels				(void);
1831 
1832 	TestSize					m_testSize;
1833 	int							m_levels;
1834 	int							m_iterationCounter;
1835 };
1836 
TextureQueryLevelsInstance(Context & context,const bool isVertexCase,const TextureSpec & textureSpec)1837 TextureQueryLevelsInstance::TextureQueryLevelsInstance (Context&				context,
1838 														const bool				isVertexCase,
1839 														const TextureSpec&		textureSpec)
1840 	: TextureQueryInstance		(context, isVertexCase, textureSpec)
1841 	, m_testSize				()
1842 	, m_levels					(0)
1843 	, m_iterationCounter		(0)
1844 {
1845 	deMemset(&m_testSize, 0, sizeof(TestSize));
1846 
1847 	m_renderSize = tcu::UVec2(1, 1);
1848 }
1849 
~TextureQueryLevelsInstance(void)1850 TextureQueryLevelsInstance::~TextureQueryLevelsInstance (void)
1851 {
1852 }
1853 
iterate(void)1854 tcu::TestStatus TextureQueryLevelsInstance::iterate (void)
1855 {
1856 	const TestSize testSizes[] =
1857 	{
1858 		{ tcu::IVec3(1, 2, 1),			0	},
1859 		{ tcu::IVec3(1, 2, 1),			1	},
1860 
1861 		{ tcu::IVec3(1, 3, 2),			0	},
1862 		{ tcu::IVec3(1, 3, 2),			1	},
1863 
1864 		{ tcu::IVec3(100, 31, 18),		0	},
1865 		{ tcu::IVec3(100, 31, 18),		1	},
1866 		{ tcu::IVec3(100, 31, 18),		2	},
1867 		{ tcu::IVec3(100, 31, 18),		3	},
1868 		{ tcu::IVec3(100, 31, 18),		4	},
1869 		{ tcu::IVec3(100, 31, 18),		5	},
1870 		{ tcu::IVec3(100, 31, 18),		6	},
1871 
1872 		{ tcu::IVec3(100, 128, 32),		0	},
1873 		{ tcu::IVec3(100, 128, 32),		1	},
1874 		{ tcu::IVec3(100, 128, 32),		2	},
1875 		{ tcu::IVec3(100, 128, 32),		3	},
1876 		{ tcu::IVec3(100, 128, 32),		4	},
1877 		{ tcu::IVec3(100, 128, 32),		5	},
1878 		{ tcu::IVec3(100, 128, 32),		6	},
1879 		{ tcu::IVec3(100, 128, 32),		7	},
1880 
1881 		// pow 2
1882 		{ tcu::IVec3(128, 64, 32),		0	},
1883 		{ tcu::IVec3(128, 64, 32),		1	},
1884 		{ tcu::IVec3(128, 64, 32),		2	},
1885 		{ tcu::IVec3(128, 64, 32),		3	},
1886 		{ tcu::IVec3(128, 64, 32),		4	},
1887 		{ tcu::IVec3(128, 64, 32),		5	},
1888 		{ tcu::IVec3(128, 64, 32),		6	},
1889 		{ tcu::IVec3(128, 64, 32),		7	},
1890 
1891 		// w == h
1892 		{ tcu::IVec3(1, 1, 1),			0	},
1893 		{ tcu::IVec3(64, 64, 64),		0	},
1894 		{ tcu::IVec3(64, 64, 64),		1	},
1895 		{ tcu::IVec3(64, 64, 64),		2	},
1896 		{ tcu::IVec3(64, 64, 64),		3	},
1897 		{ tcu::IVec3(64, 64, 64),		4	},
1898 		{ tcu::IVec3(64, 64, 64),		5	},
1899 		{ tcu::IVec3(64, 64, 64),		6	},
1900 
1901 		// w == h and d % 6 == 0 (for cube array)
1902 		{ tcu::IVec3(1, 1, 6),			0	},
1903 		{ tcu::IVec3(32, 32, 12),		0	},
1904 		{ tcu::IVec3(32, 32, 12),		1	},
1905 		{ tcu::IVec3(32, 32, 12),		2	},
1906 		{ tcu::IVec3(32, 32, 12),		3	},
1907 		{ tcu::IVec3(32, 32, 12),		4	},
1908 		{ tcu::IVec3(32, 32, 12),		5	},
1909 	};
1910 	const int lastIterationIndex = DE_LENGTH_OF_ARRAY(testSizes) + 1;
1911 
1912 	m_iterationCounter++;
1913 
1914 	if (m_iterationCounter == lastIterationIndex)
1915 		return tcu::TestStatus::pass("Pass");
1916 	else
1917 	{
1918 		// set current test size
1919 		m_testSize = testSizes[m_iterationCounter - 1];
1920 
1921 		if (!testTextureLevels())
1922 			return tcu::TestStatus::fail("Got unexpected result");
1923 
1924 		return tcu::TestStatus::incomplete();
1925 	}
1926 }
1927 
testTextureLevels(void)1928 bool TextureQueryLevelsInstance::testTextureLevels (void)
1929 {
1930 	tcu::TestLog&			log				= m_context.getTestContext().getLog();
1931 	bool					success			= true;
1932 
1933 	// skip incompatible cases
1934 	if (!isValidCase(m_textureSpec.type, m_testSize.textureSize, 0, m_testSize.lodBase))
1935 		return true;
1936 
1937 	// setup texture
1938 	initTexture();
1939 
1940 	// calculate accessible levels
1941 	{
1942 		const int	mipLevels	= deLog2Floor32(getMaxTextureSize(m_textureSpec.type, m_testSize.textureSize)) + 1;
1943 
1944 		m_levels = mipLevels - m_testSize.lodBase;
1945 		DE_ASSERT(m_levels > 0);
1946 
1947 		log << tcu::TestLog::Message << "Expected levels: " << m_levels << tcu::TestLog::EndMessage;
1948 	}
1949 
1950 	// render
1951 	TextureQueryInstance::render();
1952 
1953 	// test
1954 	{
1955 		const tcu::TextureLevel&	result				= getResultImage();
1956 		tcu::IVec4					output				= result.getAccess().getPixelInt(0, 0);
1957 
1958 		if (output.x() == m_levels)
1959 		{
1960 			// success
1961 			log << tcu::TestLog::Message << "Passed" << tcu::TestLog::EndMessage;
1962 		}
1963 		else
1964 		{
1965 			// failure
1966 			log << tcu::TestLog::Message << "Result: " << output.x() << tcu::TestLog::EndMessage;
1967 			log << tcu::TestLog::Message << "Failed" << tcu::TestLog::EndMessage;
1968 			success = false;
1969 		}
1970 	}
1971 
1972 	log << tcu::TestLog::Message << tcu::TestLog::EndMessage;
1973 
1974 	return success;
1975 }
1976 
initTexture(void)1977 void TextureQueryLevelsInstance::initTexture (void)
1978 {
1979 	tcu::TestLog&			log					= m_context.getTestContext().getLog();
1980 	int						numLevels			= m_testSize.lodBase + 1;
1981 	TextureBindingSp		textureBinding;
1982 
1983 	log << tcu::TestLog::Message << "Image size: " << getTextureSizeString(m_textureSpec.type, m_testSize.textureSize) << tcu::TestLog::EndMessage;
1984 	log << tcu::TestLog::Message << "Base level: " << m_testSize.lodBase << tcu::TestLog::EndMessage;
1985 
1986 	textureBinding = createEmptyTexture(m_textureSpec.format, m_textureSpec.type, m_testSize.textureSize, numLevels, m_testSize.lodBase, m_textureSpec.sampler);
1987 
1988 	m_textures.clear();
1989 	m_textures.push_back(textureBinding);
1990 }
1991 
getQueryLodFuncTextCoordComps(TextureType type)1992 static int getQueryLodFuncTextCoordComps (TextureType type)
1993 {
1994 	switch (type)
1995 	{
1996 		case TEXTURETYPE_1D:
1997 		case TEXTURETYPE_1D_ARRAY:
1998 			return 1;
1999 
2000 		case TEXTURETYPE_2D:
2001 		case TEXTURETYPE_2D_ARRAY:
2002 			return 2;
2003 
2004 		case TEXTURETYPE_3D:
2005 		case TEXTURETYPE_CUBE_MAP:
2006 		case TEXTURETYPE_CUBE_ARRAY:
2007 			return 3;
2008 
2009 		default:
2010 			DE_ASSERT(false);
2011 			return 0;
2012 	}
2013 }
2014 
2015 class TextureQueryLodInstance : public TextureQueryInstance
2016 {
2017 public:
2018 								TextureQueryLodInstance			(Context&					context,
2019 																 const bool					isVertexCase,
2020 																 const TextureSpec&			textureSpec);
2021 	virtual						~TextureQueryLodInstance		(void);
2022 
2023 	virtual tcu::TestStatus		iterate							(void);
2024 
2025 protected:
2026 	virtual void				setupDefaultInputs				(void);
2027 
2028 private:
2029 	void						initTexture						(void);
2030 	float						computeLevelFromLod				(float computedLod) const;
2031 	vector<float>				computeQuadTexCoord				(void) const;
2032 
2033 	tcu::Vec4					m_minCoord;
2034 	tcu::Vec4					m_maxCoord;
2035 	tcu::Vec2					m_lodBounds;
2036 	tcu::Vec2					m_levelBounds;
2037 };
2038 
TextureQueryLodInstance(Context & context,const bool isVertexCase,const TextureSpec & textureSpec)2039 TextureQueryLodInstance::TextureQueryLodInstance (Context&					context,
2040 												  const bool				isVertexCase,
2041 												  const TextureSpec&		textureSpec)
2042 	: TextureQueryInstance		(context, isVertexCase, textureSpec)
2043 	, m_minCoord				()
2044 	, m_maxCoord				()
2045 	, m_lodBounds				()
2046 	, m_levelBounds				()
2047 {
2048 	// setup texture
2049 	initTexture();
2050 
2051 	// init min/max coords
2052 	switch (m_textureSpec.type)
2053 	{
2054 		case TEXTURETYPE_1D:
2055 		case TEXTURETYPE_1D_ARRAY:
2056 			m_minCoord		= Vec4(-0.2f,  0.0f,  0.0f,  0.0f);
2057 			m_maxCoord		= Vec4( 1.5f,  0.0f,  0.0f,  0.0f);
2058 			break;
2059 
2060 		case TEXTURETYPE_2D:
2061 		case TEXTURETYPE_2D_ARRAY:
2062 			m_minCoord		= Vec4(-0.2f, -0.4f,  0.0f,  0.0f);
2063 			m_maxCoord		= Vec4( 1.5f,  2.3f,  0.0f,  0.0f);
2064 			break;
2065 
2066 		case TEXTURETYPE_3D:
2067 			m_minCoord		= Vec4(-1.2f, -1.4f,  0.1f,  0.0f);
2068 			m_maxCoord		= Vec4( 1.5f,  2.3f,  2.3f,  0.0f);
2069 			break;
2070 
2071 		case TEXTURETYPE_CUBE_MAP:
2072 		case TEXTURETYPE_CUBE_ARRAY:
2073 			m_minCoord		= Vec4(-1.0f, -1.0f,  1.01f,  0.0f);
2074 			m_maxCoord		= Vec4( 1.0f,  1.0f,  1.01f,  0.0f);
2075 			break;
2076 
2077 		default:
2078 			DE_ASSERT(false);
2079 			break;
2080 	}
2081 
2082 	// calculate lod and accessed level
2083 	{
2084 		const tcu::UVec2&		viewportSize		= getViewportSize();
2085 		const float				lodEps				= (1.0f / float(1u << m_context.getDeviceProperties().limits.mipmapPrecisionBits)) + 0.008f;
2086 
2087 		switch (m_textureSpec.type)
2088 		{
2089 			case TEXTURETYPE_1D:
2090 			case TEXTURETYPE_1D_ARRAY:
2091 			{
2092 				const float	dudx	= (m_maxCoord[0]-m_minCoord[0])*(float)m_textureSpec.width	/ (float)viewportSize[0];
2093 
2094 				m_lodBounds[0]		= computeLodFromDerivates(LODMODE_MIN_BOUND, dudx, 0.0f)-lodEps;
2095 				m_lodBounds[1]		= computeLodFromDerivates(LODMODE_MAX_BOUND, dudx, 0.0f)+lodEps;
2096 				break;
2097 			}
2098 
2099 			case TEXTURETYPE_2D:
2100 			case TEXTURETYPE_2D_ARRAY:
2101 			{
2102 				const float	dudx	= (m_maxCoord[0]-m_minCoord[0])*(float)m_textureSpec.width	/ (float)viewportSize[0];
2103 				const float	dvdy	= (m_maxCoord[1]-m_minCoord[1])*(float)m_textureSpec.height	/ (float)viewportSize[1];
2104 
2105 				m_lodBounds[0]		= computeLodFromDerivates(LODMODE_MIN_BOUND, dudx, 0.0f, 0.0f, dvdy)-lodEps;
2106 				m_lodBounds[1]		= computeLodFromDerivates(LODMODE_MAX_BOUND, dudx, 0.0f, 0.0f, dvdy)+lodEps;
2107 				break;
2108 			}
2109 
2110 			case TEXTURETYPE_CUBE_MAP:
2111 			case TEXTURETYPE_CUBE_ARRAY:
2112 			{
2113 				// Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
2114 				DE_ASSERT(de::abs(m_minCoord[2] - m_maxCoord[2]) < 0.005);
2115 				DE_ASSERT(de::abs(m_minCoord[0]) < de::abs(m_minCoord[2]) && de::abs(m_maxCoord[0]) < de::abs(m_minCoord[2]));
2116 				DE_ASSERT(de::abs(m_minCoord[1]) < de::abs(m_minCoord[2]) && de::abs(m_maxCoord[1]) < de::abs(m_minCoord[2]));
2117 
2118 				tcu::CubeFaceFloatCoords	c00		= tcu::getCubeFaceCoords(Vec3(m_minCoord[0], m_minCoord[1], m_minCoord[2]));
2119 				tcu::CubeFaceFloatCoords	c10		= tcu::getCubeFaceCoords(Vec3(m_maxCoord[0], m_minCoord[1], m_minCoord[2]));
2120 				tcu::CubeFaceFloatCoords	c01		= tcu::getCubeFaceCoords(Vec3(m_minCoord[0], m_maxCoord[1], m_minCoord[2]));
2121 				float						dudx	= (c10.s - c00.s)*(float)m_textureSpec.width	/ (float)viewportSize[0];
2122 				float						dvdy	= (c01.t - c00.t)*(float)m_textureSpec.height	/ (float)viewportSize[1];
2123 
2124 				m_lodBounds[0]		= computeLodFromDerivates(LODMODE_MIN_BOUND, dudx, 0.0f, 0.0f, dvdy)-lodEps;
2125 				m_lodBounds[1]		= computeLodFromDerivates(LODMODE_MAX_BOUND, dudx, 0.0f, 0.0f, dvdy)+lodEps;
2126 				break;
2127 			}
2128 
2129 			case TEXTURETYPE_3D:
2130 			{
2131 				const float	dudx	= (m_maxCoord[0]-m_minCoord[0])*(float)m_textureSpec.width		/ (float)viewportSize[0];
2132 				const float	dvdy	= (m_maxCoord[1]-m_minCoord[1])*(float)m_textureSpec.height		/ (float)viewportSize[1];
2133 				const float	dwdx	= (m_maxCoord[2]-m_minCoord[2])*0.5f*(float)m_textureSpec.depth	/ (float)viewportSize[0];
2134 				const float	dwdy	= (m_maxCoord[2]-m_minCoord[2])*0.5f*(float)m_textureSpec.depth	/ (float)viewportSize[1];
2135 
2136 				m_lodBounds[0]		= computeLodFromDerivates(LODMODE_MIN_BOUND, dudx, 0.0f, dwdx, 0.0f, dvdy, dwdy)-lodEps;
2137 				m_lodBounds[1]		= computeLodFromDerivates(LODMODE_MAX_BOUND, dudx, 0.0f, dwdx, 0.0f, dvdy, dwdy)+lodEps;
2138 				break;
2139 			}
2140 
2141 			default:
2142 				DE_ASSERT(false);
2143 				break;
2144 		}
2145 
2146 		m_levelBounds[0] = computeLevelFromLod(m_lodBounds[0]);
2147 		m_levelBounds[1] = computeLevelFromLod(m_lodBounds[1]);
2148 	}
2149 }
2150 
~TextureQueryLodInstance(void)2151 TextureQueryLodInstance::~TextureQueryLodInstance (void)
2152 {
2153 }
2154 
iterate(void)2155 tcu::TestStatus TextureQueryLodInstance::iterate (void)
2156 {
2157 	tcu::TestLog&		log		= m_context.getTestContext().getLog();
2158 
2159 	log << tcu::TestLog::Message << "Expected: level in range " << m_levelBounds << ", lod in range " << m_lodBounds << tcu::TestLog::EndMessage;
2160 
2161 	// render
2162 	TextureQueryInstance::render();
2163 
2164 	// test
2165 	{
2166 		const tcu::TextureLevel&	result		= getResultImage();
2167 		const tcu::Vec4				output		= result.getAccess().getPixel(0, 0);
2168 		const float					resLevel	= output.x();
2169 		const float					resLod		= output.y();
2170 
2171 		if (de::inRange(resLevel, m_levelBounds[0], m_levelBounds[1]) && de::inRange(resLod, m_lodBounds[0], m_lodBounds[1]))
2172 		{
2173 			// success
2174 			log << tcu::TestLog::Message << "Passed" << tcu::TestLog::EndMessage;
2175 			return tcu::TestStatus::pass("Pass");
2176 		}
2177 		else
2178 		{
2179 			// failure
2180 			log << tcu::TestLog::Message << "Result: level: " << resLevel << ", lod: " << resLod << tcu::TestLog::EndMessage;
2181 			log << tcu::TestLog::Message << "Failed" << tcu::TestLog::EndMessage;
2182 			return tcu::TestStatus::fail("Got unexpected result");
2183 		}
2184 	}
2185 }
2186 
setupDefaultInputs(void)2187 void TextureQueryLodInstance::setupDefaultInputs (void)
2188 {
2189 	TextureQueryInstance::setupDefaultInputs();
2190 
2191 	const deUint32			numVertices			= 4;
2192 	const vector<float>		texCoord			= computeQuadTexCoord();
2193 	const int				texCoordComps		= getQueryLodFuncTextCoordComps(m_textureSpec.type);
2194 	const vk::VkFormat		coordFormats[]		=
2195 	{
2196 		vk::VK_FORMAT_R32_SFLOAT,
2197 		vk::VK_FORMAT_R32G32_SFLOAT,
2198 		vk::VK_FORMAT_R32G32B32_SFLOAT
2199 	};
2200 
2201 	DE_ASSERT(de::inRange(texCoordComps, 1, 3));
2202 	DE_ASSERT((int)texCoord.size() == texCoordComps * 4);
2203 
2204 	addAttribute(1u, coordFormats[texCoordComps - 1], (deUint32)(texCoordComps * sizeof(float)), numVertices, texCoord.data());
2205 }
2206 
initTexture(void)2207 void TextureQueryLodInstance::initTexture (void)
2208 {
2209 	tcu::TestLog&			log					= m_context.getTestContext().getLog();
2210 	tcu::IVec3				textureSize			(m_textureSpec.width, m_textureSpec.height, m_textureSpec.depth);
2211 	TextureBindingSp		textureBinding;
2212 
2213 	DE_ASSERT(m_textures.empty());
2214 
2215 	log << tcu::TestLog::Message << "Image size: " << getTextureSizeString(m_textureSpec.type, textureSize) << tcu::TestLog::EndMessage;
2216 
2217 	textureBinding = createEmptyTexture(m_textureSpec.format, m_textureSpec.type, textureSize, m_textureSpec.numLevels, 0 /* lodBase */, m_textureSpec.sampler);
2218 
2219 	m_textures.push_back(textureBinding);
2220 }
2221 
computeLevelFromLod(float computedLod) const2222 float TextureQueryLodInstance::computeLevelFromLod (float computedLod) const
2223 {
2224 	const int	maxAccessibleLevel	= m_textureSpec.numLevels - 1;
2225 
2226 	// Clamp the computed LOD to the range of accessible levels.
2227 	computedLod = deFloatClamp(computedLod, 0.0f, (float)maxAccessibleLevel);
2228 
2229 	// Return a value according to the min filter.
2230 	switch (m_textureSpec.sampler.minFilter)
2231 	{
2232 		case tcu::Sampler::LINEAR:
2233 		case tcu::Sampler::NEAREST:
2234 			return 0.0f;
2235 
2236 		case tcu::Sampler::NEAREST_MIPMAP_NEAREST:
2237 		case tcu::Sampler::LINEAR_MIPMAP_NEAREST:
2238 			return deFloatClamp(deFloatCeil(computedLod + 0.5f) - 1.0f, 0.0f, (float)maxAccessibleLevel);
2239 
2240 		case tcu::Sampler::NEAREST_MIPMAP_LINEAR:
2241 		case tcu::Sampler::LINEAR_MIPMAP_LINEAR:
2242 			return computedLod;
2243 
2244 		default:
2245 			DE_ASSERT(false);
2246 			return 0.0f;
2247 	}
2248 }
2249 
computeQuadTexCoord(void) const2250 vector<float> TextureQueryLodInstance::computeQuadTexCoord (void) const
2251 {
2252 	vector<float>	res;
2253 	tcu::Mat4		coordTransMat;
2254 
2255 	{
2256 		Vec4 s = m_maxCoord - m_minCoord;
2257 		Vec4 b = m_minCoord;
2258 
2259 		float baseCoordTrans[] =
2260 		{
2261 			s.x(),		0.0f,		0.f,	b.x(),
2262 			0.f,		s.y(),		0.f,	b.y(),
2263 			s.z()/2.f,	-s.z()/2.f,	0.f,	s.z()/2.f + b.z(),
2264 			-s.w()/2.f,	s.w()/2.f,	0.f,	s.w()/2.f + b.w()
2265 		};
2266 
2267 		coordTransMat = tcu::Mat4(baseCoordTrans);
2268 	}
2269 
2270 	const int		texCoordComps	= getQueryLodFuncTextCoordComps(m_textureSpec.type);
2271 	Vec4			coords[4]		=
2272 	{
2273 		coordTransMat * tcu::Vec4(0, 0, 0, 1),
2274 		coordTransMat * tcu::Vec4(0, 1, 0, 1),
2275 		coordTransMat * tcu::Vec4(1, 0, 0, 1),
2276 		coordTransMat * tcu::Vec4(1, 1, 0, 1)
2277 	};
2278 
2279 	res.resize(4 * texCoordComps);
2280 
2281 	for (int ndx = 0; ndx < 4; ndx++)
2282 		deMemcpy(&res[ndx * texCoordComps], coords[ndx].getPtr(), texCoordComps * sizeof(float));
2283 
2284 	return res;
2285 }
2286 
2287 class TextureQueryCase : public ShaderRenderCase
2288 {
2289 public:
2290 								TextureQueryCase				(tcu::TestContext&			testCtx,
2291 																 const std::string&			name,
2292 																 const std::string&			desc,
2293 																 const std::string&			samplerType,
2294 																 const TextureSpec&			texture,
2295 																 bool						isVertexCase,
2296 																 QueryFunction				function);
2297 	virtual						~TextureQueryCase				(void);
2298 
2299 	virtual TestInstance*		createInstance					(Context& context) const;
2300 
2301 protected:
2302 	void						initShaderSources				(void);
2303 
2304 	const std::string			m_samplerTypeStr;
2305 	const TextureSpec			m_textureSpec;
2306 	const QueryFunction			m_function;
2307 };
2308 
TextureQueryCase(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,const std::string & samplerType,const TextureSpec & texture,bool isVertexCase,QueryFunction function)2309 TextureQueryCase::TextureQueryCase (tcu::TestContext&		testCtx,
2310 									const std::string&		name,
2311 									const std::string&		desc,
2312 									const std::string&		samplerType,
2313 									const TextureSpec&		texture,
2314 									bool					isVertexCase,
2315 									QueryFunction			function)
2316 	: ShaderRenderCase	(testCtx, name, desc, isVertexCase, (ShaderEvaluator*)DE_NULL, DE_NULL, DE_NULL)
2317 	, m_samplerTypeStr	(samplerType)
2318 	, m_textureSpec		(texture)
2319 	, m_function		(function)
2320 {
2321 	initShaderSources();
2322 }
2323 
~TextureQueryCase(void)2324 TextureQueryCase::~TextureQueryCase (void)
2325 {
2326 }
2327 
createInstance(Context & context) const2328 TestInstance* TextureQueryCase::createInstance (Context& context) const
2329 {
2330 	switch (m_function)
2331 	{
2332 		case QUERYFUNCTION_TEXTURESIZE:				return new TextureSizeInstance(context, m_isVertexCase, m_textureSpec);
2333 		case QUERYFUNCTION_TEXTUREQUERYLOD:			return new TextureQueryLodInstance(context, m_isVertexCase, m_textureSpec);
2334 		case QUERYFUNCTION_TEXTUREQUERYLEVELS:		return new TextureQueryLevelsInstance(context, m_isVertexCase, m_textureSpec);
2335 		case QUERYFUNCTION_TEXTURESAMPLES:			return new TextureSamplesInstance(context, m_isVertexCase, m_textureSpec);
2336 		default:
2337 			DE_ASSERT(false);
2338 			return DE_NULL;
2339 	}
2340 }
2341 
initShaderSources(void)2342 void TextureQueryCase::initShaderSources (void)
2343 {
2344 	std::ostringstream		vert;
2345 	std::ostringstream		frag;
2346 	std::ostringstream&		op			= m_isVertexCase ? vert : frag;
2347 	glu::GLSLVersion		version		= glu::GLSL_VERSION_LAST;
2348 
2349 	DE_ASSERT(m_function != QUERYFUNCTION_TEXTUREQUERYLOD || !m_isVertexCase);
2350 
2351 	switch (m_function)
2352 	{
2353 		case QUERYFUNCTION_TEXTURESIZE:
2354 			if (m_textureSpec.type == TEXTURETYPE_1D || m_textureSpec.type == TEXTURETYPE_1D_ARRAY || m_textureSpec.type == TEXTURETYPE_CUBE_ARRAY)
2355 				version = glu::GLSL_VERSION_420;
2356 			else
2357 				version = glu::GLSL_VERSION_310_ES;
2358 			break;
2359 
2360 		case QUERYFUNCTION_TEXTUREQUERYLOD:
2361 			version = glu::GLSL_VERSION_420;
2362 			break;
2363 
2364 		case QUERYFUNCTION_TEXTUREQUERYLEVELS:
2365 			version = glu::GLSL_VERSION_430;
2366 			break;
2367 
2368 		case QUERYFUNCTION_TEXTURESAMPLES:
2369 			version = glu::GLSL_VERSION_450;
2370 			break;
2371 
2372 		default:
2373 			DE_ASSERT(false);
2374 			break;
2375 	}
2376 
2377 	vert << glu::getGLSLVersionDeclaration(version) << "\n"
2378 		 << "layout(location = 0) in highp vec4 a_position;\n";
2379 
2380 	frag << glu::getGLSLVersionDeclaration(version) << "\n"
2381 		 << "layout(location = 0) out mediump vec4 o_color;\n";
2382 
2383 	if (m_isVertexCase)
2384 	{
2385 		vert << "layout(location = 0) out mediump vec4 v_color;\n";
2386 		frag << "layout(location = 0) in mediump vec4 v_color;\n";
2387 	}
2388 
2389 	if (m_function == QUERYFUNCTION_TEXTUREQUERYLOD)
2390 	{
2391 		const int		texCoordComps	= getQueryLodFuncTextCoordComps(m_textureSpec.type);
2392 		const char*		coordTypeName	= glu::getDataTypeName(glu::getDataTypeFloatVec(texCoordComps));
2393 
2394 		vert << "layout (location = 1) in highp " << coordTypeName << " a_texCoord;\n";
2395 		vert << "layout (location = 0) out highp " << coordTypeName << " v_texCoord;\n";
2396 		frag << "layout (location = 0) in highp " << coordTypeName << " v_texCoord;\n";
2397 	}
2398 
2399 	// uniforms
2400 	op << "layout(set = 0, binding = 0) uniform highp " << m_samplerTypeStr << " u_sampler;\n";
2401 	if (m_function == QUERYFUNCTION_TEXTURESIZE)
2402 		op << "layout(set = 0, binding = 1) uniform buf0 { highp int u_lod; };\n";
2403 
2404 	if (version != glu::GLSL_VERSION_310_ES)
2405 		vert << "out gl_PerVertex {\n"
2406 			 << "\tvec4 gl_Position;\n"
2407 			 << "};\n";
2408 
2409 	vert << "\nvoid main()\n{\n"
2410 		 << "\tgl_Position = a_position;\n";
2411 	frag << "\nvoid main()\n{\n";
2412 
2413 	if (m_isVertexCase)
2414 		vert << "\tv_color = ";
2415 	else
2416 		frag << "\to_color = ";
2417 
2418 	// op
2419 	{
2420 		op << "vec4(";
2421 
2422 		switch (m_function)
2423 		{
2424 			case QUERYFUNCTION_TEXTURESIZE:
2425 			{
2426 				const int		resultComponents	= glu::getDataTypeScalarSize(getTextureSizeFuncResultType(m_textureSpec.type));
2427 
2428 				op << "textureSize(u_sampler, u_lod)";
2429 				for (int ndx = 0; ndx < 3 - resultComponents; ndx++)
2430 					op << ", 0.0";
2431 				op << ", 1.0";
2432 
2433 				break;
2434 			}
2435 
2436 			case QUERYFUNCTION_TEXTUREQUERYLOD:
2437 				op << "textureQueryLod(u_sampler, v_texCoord), 0.0, 1.0";
2438 				break;
2439 
2440 			case QUERYFUNCTION_TEXTUREQUERYLEVELS:
2441 				op << "textureQueryLevels(u_sampler), 0.0, 0.0, 1.0";
2442 				break;
2443 
2444 			case QUERYFUNCTION_TEXTURESAMPLES:
2445 				op << "textureSamples(u_sampler), 0.0, 0.0, 1.0";
2446 				break;
2447 
2448 			default:
2449 				DE_ASSERT(false);
2450 				break;
2451 		}
2452 
2453 		op << ");\n";
2454 	}
2455 
2456 	if (m_isVertexCase)
2457 		frag << "\to_color = v_color;\n";
2458 
2459 	if (m_function == QUERYFUNCTION_TEXTUREQUERYLOD)
2460 		vert << "\tv_texCoord = a_texCoord;\n";
2461 
2462 	vert << "}\n";
2463 	frag << "}\n";
2464 
2465 	m_vertShaderSource = vert.str();
2466 	m_fragShaderSource = frag.str();
2467 }
2468 
2469 class ShaderTextureFunctionTests : public tcu::TestCaseGroup
2470 {
2471 public:
2472 									ShaderTextureFunctionTests		(tcu::TestContext& context);
2473 	virtual							~ShaderTextureFunctionTests		(void);
2474 	virtual void					init							(void);
2475 
2476 private:
2477 									ShaderTextureFunctionTests		(const ShaderTextureFunctionTests&);		// not allowed!
2478 	ShaderTextureFunctionTests&		operator=						(const ShaderTextureFunctionTests&);		// not allowed!
2479 };
2480 
ShaderTextureFunctionTests(tcu::TestContext & context)2481 ShaderTextureFunctionTests::ShaderTextureFunctionTests (tcu::TestContext& context)
2482 	: TestCaseGroup(context, "texture_functions", "Texture Access Function Tests")
2483 {
2484 }
2485 
~ShaderTextureFunctionTests(void)2486 ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void)
2487 {
2488 }
2489 
2490 enum CaseFlags
2491 {
2492 	VERTEX		= (1<<0),
2493 	FRAGMENT	= (1<<1),
2494 	BOTH		= VERTEX|FRAGMENT
2495 };
2496 
2497 struct TexFuncCaseSpec
2498 {
2499 	const char*			name;
2500 	TextureLookupSpec	lookupSpec;
2501 	TextureSpec			texSpec;
2502 	TexEvalFunc			evalFunc;
2503 	deUint32			flags;
2504 };
2505 
2506 #define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, USEOFFSET, OFFSET, TEXSPEC, EVALFUNC, FLAGS) \
2507 	{ #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, tcu::Vec3(0.0f), tcu::Vec3(0.0f), tcu::Vec3(0.0f), tcu::Vec3(0.0f), USEOFFSET, OFFSET), TEXSPEC, EVALFUNC, FLAGS }
2508 #define GRAD_CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, MINDX, MAXDX, MINDY, MAXDY, USEOFFSET, OFFSET, TEXSPEC, EVALFUNC, FLAGS) \
2509 	{ #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, false, 0.0f, 0.0f, MINDX, MAXDX, MINDY, MAXDY, USEOFFSET, OFFSET), TEXSPEC, EVALFUNC, FLAGS }
2510 
2511 class SparseShaderTextureFunctionInstance : public ShaderTextureFunctionInstance
2512 {
2513 public:
2514 				SparseShaderTextureFunctionInstance		(Context&					context,
2515 														const bool					isVertexCase,
2516 														const ShaderEvaluator&		evaluator,
2517 														const UniformSetup&			uniformSetup,
2518 														const TextureLookupSpec&	lookupSpec,
2519 														const TextureSpec&			textureSpec,
2520 														const TexLookupParams&		lookupParams,
2521 														const ImageBackingMode		imageBackingMode = IMAGE_BACKING_MODE_SPARSE);
2522 	virtual		~SparseShaderTextureFunctionInstance	(void);
2523 };
2524 
SparseShaderTextureFunctionInstance(Context & context,const bool isVertexCase,const ShaderEvaluator & evaluator,const UniformSetup & uniformSetup,const TextureLookupSpec & lookupSpec,const TextureSpec & textureSpec,const TexLookupParams & lookupParams,const ImageBackingMode imageBackingMode)2525 SparseShaderTextureFunctionInstance::SparseShaderTextureFunctionInstance (Context&					context,
2526 																		 const bool					isVertexCase,
2527 																		 const ShaderEvaluator&		evaluator,
2528 																		 const UniformSetup&		uniformSetup,
2529 																		 const TextureLookupSpec&	lookupSpec,
2530 																		 const TextureSpec&			textureSpec,
2531 																		 const TexLookupParams&		lookupParams,
2532 																		 const ImageBackingMode		imageBackingMode)
2533 	: ShaderTextureFunctionInstance (context, isVertexCase, evaluator, uniformSetup, lookupSpec, textureSpec, lookupParams, imageBackingMode)
2534 {
2535 }
2536 
~SparseShaderTextureFunctionInstance(void)2537 SparseShaderTextureFunctionInstance::~SparseShaderTextureFunctionInstance (void)
2538 {
2539 }
2540 
2541 class SparseShaderTextureFunctionCase : public ShaderTextureFunctionCase
2542 {
2543 public:
2544 							SparseShaderTextureFunctionCase		(tcu::TestContext&			testCtx,
2545 																const std::string&			name,
2546 																const std::string&			desc,
2547 																const TextureLookupSpec&	lookup,
2548 																const TextureSpec&			texture,
2549 																TexEvalFunc					evalFunc,
2550 																bool						isVertexCase);
2551 
2552 	virtual					~SparseShaderTextureFunctionCase	(void);
2553 
2554 	virtual	TestInstance*	createInstance						(Context& context) const;
2555 protected:
2556 	void					initShaderSources					(void);
2557 };
2558 
SparseShaderTextureFunctionCase(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,const TextureLookupSpec & lookup,const TextureSpec & texture,TexEvalFunc evalFunc,bool isVertexCase)2559 SparseShaderTextureFunctionCase::SparseShaderTextureFunctionCase (tcu::TestContext&				testCtx,
2560 																  const std::string&			name,
2561 																  const std::string&			desc,
2562 																  const TextureLookupSpec&		lookup,
2563 																  const TextureSpec&			texture,
2564 																  TexEvalFunc					evalFunc,
2565 																  bool							isVertexCase)
2566 	: ShaderTextureFunctionCase		(testCtx, name, desc, lookup, texture, evalFunc, isVertexCase)
2567 {
2568 	initShaderSources();
2569 }
2570 
initShaderSources(void)2571 void SparseShaderTextureFunctionCase::initShaderSources (void)
2572 {
2573 	const Function				function			= m_lookupSpec.function;
2574 	const bool					isVtxCase			= m_isVertexCase;
2575 	const bool					isProj				= functionHasProj(function);
2576 	const bool					isGrad				= functionHasGrad(function);
2577 	const bool					isShadow			= m_textureSpec.sampler.compare != tcu::Sampler::COMPAREMODE_NONE;
2578 	const bool					is2DProj4			= !isShadow && m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD || function == FUNCTION_TEXTUREPROJGRAD);
2579 	const bool					isIntCoord			= function == FUNCTION_TEXELFETCH;
2580 	const bool					hasLodBias			= functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias;
2581 	const int					texCoordComps		= m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3;
2582 	const int					extraCoordComps		= (isProj ? (is2DProj4 ? 2 : 1) : 0) + (isShadow ? 1 : 0);
2583 	const glu::DataType			coordType			= glu::getDataTypeFloatVec(texCoordComps+extraCoordComps);
2584 	const glu::Precision		coordPrec			= glu::PRECISION_HIGHP;
2585 	const char*					coordTypeName		= glu::getDataTypeName(coordType);
2586 	const char*					coordPrecName		= glu::getPrecisionName(coordPrec);
2587 	const tcu::TextureFormat	texFmt				= glu::mapGLInternalFormat(m_textureSpec.format);
2588 	glu::DataType				samplerType			= glu::TYPE_LAST;
2589 	const glu::DataType			gradType			= (m_textureSpec.type == TEXTURETYPE_CUBE_MAP || m_textureSpec.type == TEXTURETYPE_3D) ? glu::TYPE_FLOAT_VEC3 : glu::TYPE_FLOAT_VEC2;
2590 	const char*					gradTypeName		= glu::getDataTypeName(gradType);
2591 	const char*					baseFuncName		= DE_NULL;
2592 
2593 	DE_ASSERT(!isGrad || !hasLodBias);
2594 
2595 	switch (m_textureSpec.type)
2596 	{
2597 		case TEXTURETYPE_2D:		samplerType = isShadow ? glu::TYPE_SAMPLER_2D_SHADOW		: glu::getSampler2DType(texFmt);		break;
2598 		case TEXTURETYPE_CUBE_MAP:	samplerType = isShadow ? glu::TYPE_SAMPLER_CUBE_SHADOW		: glu::getSamplerCubeType(texFmt);		break;
2599 		case TEXTURETYPE_2D_ARRAY:	samplerType = isShadow ? glu::TYPE_SAMPLER_2D_ARRAY_SHADOW	: glu::getSampler2DArrayType(texFmt);	break;
2600 		case TEXTURETYPE_3D:		DE_ASSERT(!isShadow); samplerType = glu::getSampler3DType(texFmt);									break;
2601 		default:
2602 			DE_ASSERT(DE_FALSE);
2603 	}
2604 
2605 	// Not supported cases
2606 	switch (m_lookupSpec.function)
2607 	{
2608 		case FUNCTION_TEXTURE:			baseFuncName = "sparseTexture";			break;
2609 		case FUNCTION_TEXTURELOD:		baseFuncName = "sparseTextureLod";		break;
2610 		case FUNCTION_TEXTUREGRAD:		baseFuncName = "sparseTextureGrad";		break;
2611 		case FUNCTION_TEXELFETCH:		baseFuncName = "sparseTexelFetch";		break;
2612 		default:
2613 			DE_ASSERT(DE_FALSE);
2614 	}
2615 
2616 	std::ostringstream	vert;
2617 	std::ostringstream	frag;
2618 	std::ostringstream&	op		= isVtxCase ? vert : frag;
2619 
2620 	vert << "#version 450\n"
2621 		 << "#extension GL_ARB_sparse_texture2 : require\n"
2622 		 << "layout(location = 0) in highp vec4 a_position;\n"
2623 		 << "layout(location = 4) in " << coordPrecName << " " << coordTypeName << " a_in0;\n";
2624 
2625 	if (isGrad)
2626 	{
2627 		vert << "layout(location = 5) in " << coordPrecName << " " << gradTypeName << " a_in1;\n";
2628 		vert << "layout(location = 6) in " << coordPrecName << " " << gradTypeName << " a_in2;\n";
2629 	}
2630 	else if (hasLodBias)
2631 		vert << "layout(location = 5) in " << coordPrecName << " float a_in1;\n";
2632 
2633 	frag << "#version 450\n"
2634 		 << "#extension GL_ARB_sparse_texture2 : require\n"
2635 		 << "layout(location = 0) out mediump vec4 o_color;\n";
2636 
2637 	if (isVtxCase)
2638 	{
2639 		vert << "layout(location = 0) out mediump vec4 v_color;\n";
2640 		frag << "layout(location = 0) in mediump vec4 v_color;\n";
2641 	}
2642 	else
2643 	{
2644 		vert << "layout(location = 0) out " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
2645 		frag << "layout(location = 0) in " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
2646 
2647 		if (isGrad)
2648 		{
2649 			vert << "layout(location = 1) out " << coordPrecName << " " << gradTypeName << " v_gradX;\n";
2650 			vert << "layout(location = 2) out " << coordPrecName << " " << gradTypeName << " v_gradY;\n";
2651 			frag << "layout(location = 1) in " << coordPrecName << " " << gradTypeName << " v_gradX;\n";
2652 			frag << "layout(location = 2) in " << coordPrecName << " " << gradTypeName << " v_gradY;\n";
2653 		}
2654 		else if (hasLodBias)
2655 		{
2656 			vert << "layout(location = 1) out " << coordPrecName << " float v_lodBias;\n";
2657 			frag << "layout(location = 1) in " << coordPrecName << " float v_lodBias;\n";
2658 		}
2659 	}
2660 
2661 	// Uniforms
2662 	op << "layout(set = 0, binding = 0) uniform highp " << glu::getDataTypeName(samplerType) << " u_sampler;\n"
2663 	   << "layout(set = 0, binding = 1) uniform buf0 { highp vec4 u_scale; };\n"
2664 	   << "layout(set = 0, binding = 2) uniform buf1 { highp vec4 u_bias; };\n";
2665 
2666 	vert << "out gl_PerVertex {\n"
2667 		 << "	vec4 gl_Position;\n"
2668 		 << "};\n";
2669 	vert << "\nvoid main()\n{\n"
2670 		 << "\tgl_Position = a_position;\n";
2671 	frag << "\nvoid main()\n{\n";
2672 
2673 	// Op.
2674 	{
2675 		// Texel declaration
2676 		if (isShadow)
2677 			op << "\tfloat texel;\n";
2678 		else
2679 			op << "\tvec4 texel;\n";
2680 
2681 		const char*	const texCoord	= isVtxCase ? "a_in0" : "v_texCoord";
2682 		const char* const gradX		= isVtxCase ? "a_in1" : "v_gradX";
2683 		const char* const gradY		= isVtxCase ? "a_in2" : "v_gradY";
2684 		const char*	const lodBias	= isVtxCase ? "a_in1" : "v_lodBias";
2685 
2686 		op << "\tint success = " << baseFuncName;
2687 
2688 		if (m_lookupSpec.useOffset)
2689 			op << "Offset";
2690 
2691 		op << "ARB(u_sampler, ";
2692 
2693 		if (isIntCoord)
2694 			op << "ivec" << (texCoordComps+extraCoordComps) << "(";
2695 
2696 		op << texCoord;
2697 
2698 		if (isIntCoord)
2699 			op << ")";
2700 
2701 		if (isGrad)
2702 			op << ", " << gradX << ", " << gradY;
2703 
2704 		if (functionHasLod(function))
2705 		{
2706 			if (isIntCoord)
2707 				op << ", int(" << lodBias << ")";
2708 			else
2709 				op << ", " << lodBias;
2710 		}
2711 
2712 		if (m_lookupSpec.useOffset)
2713 		{
2714 			int offsetComps = m_textureSpec.type == TEXTURETYPE_3D ? 3 : 2;
2715 
2716 			op << ", ivec" << offsetComps << "(";
2717 			for (int ndx = 0; ndx < offsetComps; ndx++)
2718 			{
2719 				if (ndx != 0)
2720 					op << ", ";
2721 				op << m_lookupSpec.offset[ndx];
2722 			}
2723 			op << ")";
2724 		}
2725 
2726 		op << ", texel";
2727 
2728 		if (m_lookupSpec.useBias)
2729 			op << ", " << lodBias;
2730 
2731 		op << ");\n";
2732 
2733 		// Check sparse validity, and handle each case
2734 		op << "\tif (sparseTexelsResidentARB(success))\n";
2735 
2736 		if (isVtxCase)
2737 			vert << "\t\tv_color = ";
2738 		else
2739 			frag << "\t\to_color = ";
2740 
2741 		if (isShadow)
2742 			op << "vec4(texel, 0.0, 0.0, 1.0);\n";
2743 		else
2744 			op << "vec4(texel * u_scale + u_bias);\n";
2745 
2746 		op << "\telse\n";
2747 
2748 		// This color differs from the used colors
2749 		if (isVtxCase)
2750 			vert << "\t\tv_color = vec4(0.54117647058, 0.16862745098, 0.8862745098, 1.0);\n";
2751 		else
2752 			frag << "\t\to_color = vec4(0.54117647058, 0.16862745098, 0.8862745098, 1.0);\n";
2753 	}
2754 
2755 	if (isVtxCase)
2756 		frag << "\to_color = v_color;\n";
2757 	else
2758 	{
2759 		vert << "\tv_texCoord = a_in0;\n";
2760 
2761 		if (isGrad)
2762 		{
2763 			vert << "\tv_gradX = a_in1;\n";
2764 			vert << "\tv_gradY = a_in2;\n";
2765 		}
2766 		else if (hasLodBias)
2767 			vert << "\tv_lodBias = a_in1;\n";
2768 	}
2769 
2770 	vert << "}\n";
2771 	frag << "}\n";
2772 
2773 	m_vertShaderSource = vert.str();
2774 	m_fragShaderSource = frag.str();
2775 }
2776 
~SparseShaderTextureFunctionCase()2777 SparseShaderTextureFunctionCase::~SparseShaderTextureFunctionCase ()
2778 {
2779 }
2780 
createInstance(Context & context) const2781 TestInstance* SparseShaderTextureFunctionCase::createInstance (Context& context) const
2782 {
2783 	DE_ASSERT(m_evaluator != DE_NULL);
2784 	DE_ASSERT(m_uniformSetup != DE_NULL);
2785 	return new SparseShaderTextureFunctionInstance(context, m_isVertexCase, *m_evaluator, *m_uniformSetup, m_lookupSpec, m_textureSpec, m_lookupParams);
2786 }
2787 
createCaseGroup(tcu::TestCaseGroup * parent,const char * groupName,const char * groupDesc,const TexFuncCaseSpec * cases,int numCases)2788 static void createCaseGroup (tcu::TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases)
2789 {
2790 	de::MovePtr<tcu::TestCaseGroup>	group	(new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc));
2791 
2792 	for (int ndx = 0; ndx < numCases; ndx++)
2793 	{
2794 		std::string name = cases[ndx].name;
2795 		if (cases[ndx].flags & VERTEX)
2796 		{
2797 			if (!functionHasProj(cases[ndx].lookupSpec.function))
2798 				group->addChild(new SparseShaderTextureFunctionCase(parent->getTestContext(), ("sparse_" + name + "_vertex"),   "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, true ));
2799 			group->addChild(new ShaderTextureFunctionCase(parent->getTestContext(), (name + "_vertex"),   "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, true ));
2800 		}
2801 
2802 		if (cases[ndx].flags & FRAGMENT)
2803 		{
2804 			if (!functionHasProj(cases[ndx].lookupSpec.function))
2805 				group->addChild(new SparseShaderTextureFunctionCase(parent->getTestContext(), ("sparse_" + name + "_fragment"), "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, false));
2806 			group->addChild(new ShaderTextureFunctionCase(parent->getTestContext(), (name + "_fragment"), "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, false));
2807 		}
2808 	}
2809 
2810 	parent->addChild(group.release());
2811 }
2812 
init(void)2813 void ShaderTextureFunctionTests::init (void)
2814 {
2815 	// Samplers
2816 	static const tcu::Sampler	samplerNearestNoMipmap	(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2817 														 tcu::Sampler::NEAREST, tcu::Sampler::NEAREST,
2818 														 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE,
2819 														 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2820 	static const tcu::Sampler	samplerLinearNoMipmap	(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2821 														 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR,
2822 														 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE,
2823 														 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2824 	static const tcu::Sampler	samplerNearestMipmap	(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2825 														 tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST,
2826 														 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE,
2827 														 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2828 	static const tcu::Sampler	samplerLinearMipmap		(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2829 														 tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR,
2830 														 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE,
2831 														 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2832 
2833 	static const tcu::Sampler	samplerShadowNoMipmap	(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2834 														 tcu::Sampler::NEAREST, tcu::Sampler::NEAREST,
2835 														 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_LESS,
2836 														 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2837 	static const tcu::Sampler	samplerShadowMipmap		(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2838 														 tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST,
2839 														 0.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_LESS,
2840 														 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2841 
2842 	static const tcu::Sampler	samplerTexelFetch		(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2843 														 tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST,
2844 														 00.0f /* LOD threshold */, true /* normalized coords */, tcu::Sampler::COMPAREMODE_NONE,
2845 														 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2846 
2847 	// Default textures.
2848 	//												Type					Format					W		H		D	L	Sampler
2849 	static const TextureSpec tex2DFixed				(TEXTURETYPE_2D,		GL_RGBA8,				256,	256,	1,	1,	samplerLinearNoMipmap);
2850 	static const TextureSpec tex2DFloat				(TEXTURETYPE_2D,		GL_RGBA16F,				256,	256,	1,	1,	samplerLinearNoMipmap);
2851 	static const TextureSpec tex2DInt				(TEXTURETYPE_2D,		GL_RGBA8I,				256,	256,	1,	1,	samplerNearestNoMipmap);
2852 	static const TextureSpec tex2DUint				(TEXTURETYPE_2D,		GL_RGBA8UI,				256,	256,	1,	1,	samplerNearestNoMipmap);
2853 	static const TextureSpec tex2DMipmapFixed		(TEXTURETYPE_2D,		GL_RGBA8,				256,	256,	1,	9,	samplerLinearMipmap);
2854 	static const TextureSpec tex2DMipmapFloat		(TEXTURETYPE_2D,		GL_RGBA16F,				256,	256,	1,	9,	samplerLinearMipmap);
2855 	static const TextureSpec tex2DMipmapInt			(TEXTURETYPE_2D,		GL_RGBA8I,				256,	256,	1,	9,	samplerNearestMipmap);
2856 	static const TextureSpec tex2DMipmapUint		(TEXTURETYPE_2D,		GL_RGBA8UI,				256,	256,	1,	9,	samplerNearestMipmap);
2857 
2858 	static const TextureSpec tex2DShadow			(TEXTURETYPE_2D,		GL_DEPTH_COMPONENT16,	256,	256,	1,	1,	samplerShadowNoMipmap);
2859 	static const TextureSpec tex2DMipmapShadow		(TEXTURETYPE_2D,		GL_DEPTH_COMPONENT16,	256,	256,	1,	9,	samplerShadowMipmap);
2860 
2861 	static const TextureSpec tex2DTexelFetchFixed	(TEXTURETYPE_2D,		GL_RGBA8,				256,	256,	1,	9,	samplerTexelFetch);
2862 	static const TextureSpec tex2DTexelFetchFloat	(TEXTURETYPE_2D,		GL_RGBA16F,				256,	256,	1,	9,	samplerTexelFetch);
2863 	static const TextureSpec tex2DTexelFetchInt		(TEXTURETYPE_2D,		GL_RGBA8I,				256,	256,	1,	9,	samplerTexelFetch);
2864 	static const TextureSpec tex2DTexelFetchUint	(TEXTURETYPE_2D,		GL_RGBA8UI,				256,	256,	1,	9,	samplerTexelFetch);
2865 
2866 	static const TextureSpec texCubeFixed			(TEXTURETYPE_CUBE_MAP,	GL_RGBA8,	256,	256,	1,	1,	samplerLinearNoMipmap);
2867 	static const TextureSpec texCubeFloat			(TEXTURETYPE_CUBE_MAP,	GL_RGBA16F,	256,	256,	1,	1,	samplerLinearNoMipmap);
2868 	static const TextureSpec texCubeInt				(TEXTURETYPE_CUBE_MAP,	GL_RGBA8I,	256,	256,	1,	1,	samplerNearestNoMipmap);
2869 	static const TextureSpec texCubeUint			(TEXTURETYPE_CUBE_MAP,	GL_RGBA8UI,	256,	256,	1,	1,	samplerNearestNoMipmap);
2870 	static const TextureSpec texCubeMipmapFixed		(TEXTURETYPE_CUBE_MAP,	GL_RGBA8,	256,	256,	1,	9,	samplerLinearMipmap);
2871 	static const TextureSpec texCubeMipmapFloat		(TEXTURETYPE_CUBE_MAP,	GL_RGBA16F,	128,	128,	1,	8,	samplerLinearMipmap);
2872 	static const TextureSpec texCubeMipmapInt		(TEXTURETYPE_CUBE_MAP,	GL_RGBA8I,	256,	256,	1,	9,	samplerNearestMipmap);
2873 	static const TextureSpec texCubeMipmapUint		(TEXTURETYPE_CUBE_MAP,	GL_RGBA8UI,	256,	256,	1,	9,	samplerNearestMipmap);
2874 
2875 	static const TextureSpec texCubeShadow			(TEXTURETYPE_CUBE_MAP,	GL_DEPTH_COMPONENT16,	256,	256,	1,	1,	samplerShadowNoMipmap);
2876 	static const TextureSpec texCubeMipmapShadow	(TEXTURETYPE_CUBE_MAP,	GL_DEPTH_COMPONENT16,	256,	256,	1,	9,	samplerShadowMipmap);
2877 
2878 	static const TextureSpec tex2DArrayFixed		(TEXTURETYPE_2D_ARRAY,	GL_RGBA8,	128,	128,	4,	1,	samplerLinearNoMipmap);
2879 	static const TextureSpec tex2DArrayFloat		(TEXTURETYPE_2D_ARRAY,	GL_RGBA16F,	128,	128,	4,	1,	samplerLinearNoMipmap);
2880 	static const TextureSpec tex2DArrayInt			(TEXTURETYPE_2D_ARRAY,	GL_RGBA8I,	128,	128,	4,	1,	samplerNearestNoMipmap);
2881 	static const TextureSpec tex2DArrayUint			(TEXTURETYPE_2D_ARRAY,	GL_RGBA8UI,	128,	128,	4,	1,	samplerNearestNoMipmap);
2882 	static const TextureSpec tex2DArrayMipmapFixed	(TEXTURETYPE_2D_ARRAY,	GL_RGBA8,	128,	128,	4,	8,	samplerLinearMipmap);
2883 	static const TextureSpec tex2DArrayMipmapFloat	(TEXTURETYPE_2D_ARRAY,	GL_RGBA16F,	128,	128,	4,	8,	samplerLinearMipmap);
2884 	static const TextureSpec tex2DArrayMipmapInt	(TEXTURETYPE_2D_ARRAY,	GL_RGBA8I,	128,	128,	4,	8,	samplerNearestMipmap);
2885 	static const TextureSpec tex2DArrayMipmapUint	(TEXTURETYPE_2D_ARRAY,	GL_RGBA8UI,	128,	128,	4,	8,	samplerNearestMipmap);
2886 
2887 	static const TextureSpec tex2DArrayShadow		(TEXTURETYPE_2D_ARRAY,	GL_DEPTH_COMPONENT16,	128,	128,	4,	1,	samplerShadowNoMipmap);
2888 	static const TextureSpec tex2DArrayMipmapShadow	(TEXTURETYPE_2D_ARRAY,	GL_DEPTH_COMPONENT16,	128,	128,	4,	8,	samplerShadowMipmap);
2889 
2890 	static const TextureSpec tex2DArrayTexelFetchFixed	(TEXTURETYPE_2D_ARRAY,	GL_RGBA8,	128,	128,	4,	8,	samplerTexelFetch);
2891 	static const TextureSpec tex2DArrayTexelFetchFloat	(TEXTURETYPE_2D_ARRAY,	GL_RGBA16F,	128,	128,	4,	8,	samplerTexelFetch);
2892 	static const TextureSpec tex2DArrayTexelFetchInt	(TEXTURETYPE_2D_ARRAY,	GL_RGBA8I,	128,	128,	4,	8,	samplerTexelFetch);
2893 	static const TextureSpec tex2DArrayTexelFetchUint	(TEXTURETYPE_2D_ARRAY,	GL_RGBA8UI,	128,	128,	4,	8,	samplerTexelFetch);
2894 
2895 	static const TextureSpec tex3DFixed				(TEXTURETYPE_3D,		GL_RGBA8,	64,		32,		32,	1,	samplerLinearNoMipmap);
2896 	static const TextureSpec tex3DFloat				(TEXTURETYPE_3D,		GL_RGBA16F,	64,		32,		32,	1,	samplerLinearNoMipmap);
2897 	static const TextureSpec tex3DInt				(TEXTURETYPE_3D,		GL_RGBA8I,	64,		32,		32,	1,	samplerNearestNoMipmap);
2898 	static const TextureSpec tex3DUint				(TEXTURETYPE_3D,		GL_RGBA8UI,	64,		32,		32,	1,	samplerNearestNoMipmap);
2899 	static const TextureSpec tex3DMipmapFixed		(TEXTURETYPE_3D,		GL_RGBA8,	64,		32,		32,	7,	samplerLinearMipmap);
2900 	static const TextureSpec tex3DMipmapFloat		(TEXTURETYPE_3D,		GL_RGBA16F,	64,		32,		32,	7,	samplerLinearMipmap);
2901 	static const TextureSpec tex3DMipmapInt			(TEXTURETYPE_3D,		GL_RGBA8I,	64,		32,		32,	7,	samplerNearestMipmap);
2902 	static const TextureSpec tex3DMipmapUint		(TEXTURETYPE_3D,		GL_RGBA8UI,	64,		32,		32,	7,	samplerNearestMipmap);
2903 
2904 	static const TextureSpec tex3DTexelFetchFixed	(TEXTURETYPE_3D,		GL_RGBA8,	64,		32,		32,	7,	samplerTexelFetch);
2905 	static const TextureSpec tex3DTexelFetchFloat	(TEXTURETYPE_3D,		GL_RGBA16F,	64,		32,		32,	7,	samplerTexelFetch);
2906 	static const TextureSpec tex3DTexelFetchInt		(TEXTURETYPE_3D,		GL_RGBA8I,	64,		32,		32,	7,	samplerTexelFetch);
2907 	static const TextureSpec tex3DTexelFetchUint	(TEXTURETYPE_3D,		GL_RGBA8UI,	64,		32,		32,	7,	samplerTexelFetch);
2908 
2909 	static const TextureSpec tex1DFixed				(TEXTURETYPE_1D,		GL_RGBA8,				256,	1,	1,	1,	samplerLinearNoMipmap);
2910 	static const TextureSpec tex1DFloat				(TEXTURETYPE_1D,		GL_RGBA16F,				256,	1,	1,	1,	samplerLinearNoMipmap);
2911 	static const TextureSpec tex1DInt				(TEXTURETYPE_1D,		GL_RGBA8I,				256,	1,	1,	1,	samplerNearestNoMipmap);
2912 	static const TextureSpec tex1DUint				(TEXTURETYPE_1D,		GL_RGBA8UI,				256,	1,	1,	1,	samplerNearestNoMipmap);
2913 	static const TextureSpec tex1DMipmapFixed		(TEXTURETYPE_1D,		GL_RGBA8,				256,	1,	1,	9,	samplerLinearMipmap);
2914 	static const TextureSpec tex1DMipmapFloat		(TEXTURETYPE_1D,		GL_RGBA16F,				256,	1,	1,	9,	samplerLinearMipmap);
2915 	static const TextureSpec tex1DMipmapInt			(TEXTURETYPE_1D,		GL_RGBA8I,				256,	1,	1,	9,	samplerNearestMipmap);
2916 	static const TextureSpec tex1DMipmapUint		(TEXTURETYPE_1D,		GL_RGBA8UI,				256,	1,	1,	9,	samplerNearestMipmap);
2917 
2918 	static const TextureSpec tex1DShadow			(TEXTURETYPE_1D,		GL_DEPTH_COMPONENT16,	256,	1,	1,	1,	samplerShadowNoMipmap);
2919 	static const TextureSpec tex1DMipmapShadow		(TEXTURETYPE_1D,		GL_DEPTH_COMPONENT16,	256,	1,	1,	9,	samplerShadowMipmap);
2920 
2921 	static const TextureSpec tex1DArrayFixed		(TEXTURETYPE_1D_ARRAY,	GL_RGBA8,	256,	1,	4,	1,	samplerLinearNoMipmap);
2922 	static const TextureSpec tex1DArrayFloat		(TEXTURETYPE_1D_ARRAY,	GL_RGBA16F,	256,	1,	4,	1,	samplerLinearNoMipmap);
2923 	static const TextureSpec tex1DArrayInt			(TEXTURETYPE_1D_ARRAY,	GL_RGBA8I,	256,	1,	4,	1,	samplerNearestNoMipmap);
2924 	static const TextureSpec tex1DArrayUint			(TEXTURETYPE_1D_ARRAY,	GL_RGBA8UI,	256,	1,	4,	1,	samplerNearestNoMipmap);
2925 	static const TextureSpec tex1DArrayMipmapFixed	(TEXTURETYPE_1D_ARRAY,	GL_RGBA8,	256,	1,	4,	9,	samplerLinearMipmap);
2926 	static const TextureSpec tex1DArrayMipmapFloat	(TEXTURETYPE_1D_ARRAY,	GL_RGBA16F,	256,	1,	4,	9,	samplerLinearMipmap);
2927 	static const TextureSpec tex1DArrayMipmapInt	(TEXTURETYPE_1D_ARRAY,	GL_RGBA8I,	256,	1,	4,	9,	samplerNearestMipmap);
2928 	static const TextureSpec tex1DArrayMipmapUint	(TEXTURETYPE_1D_ARRAY,	GL_RGBA8UI,	256,	1,	4,	9,	samplerNearestMipmap);
2929 
2930 	static const TextureSpec tex1DArrayShadow		(TEXTURETYPE_1D_ARRAY,	GL_DEPTH_COMPONENT16,	256,	1,	4,	1,	samplerShadowNoMipmap);
2931 	static const TextureSpec tex1DArrayMipmapShadow	(TEXTURETYPE_1D_ARRAY,	GL_DEPTH_COMPONENT16,	256,	1,	4,	9,	samplerShadowMipmap);
2932 
2933 	static const TextureSpec texCubeArrayFixed			(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA8,	256,	256,	12,	1,	samplerLinearNoMipmap);
2934 	static const TextureSpec texCubeArrayFloat			(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA16F,	256,	256,	12,	1,	samplerLinearNoMipmap);
2935 	static const TextureSpec texCubeArrayInt			(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA8I,	256,	256,	12,	1,	samplerNearestNoMipmap);
2936 	static const TextureSpec texCubeArrayUint			(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA8UI,	256,	256,	12,	1,	samplerNearestNoMipmap);
2937 	static const TextureSpec texCubeArrayMipmapFixed	(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA8,	256,	256,	12,	9,	samplerLinearMipmap);
2938 	static const TextureSpec texCubeArrayMipmapFloat	(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA16F,	128,	128,	12,	8,	samplerLinearMipmap);
2939 	static const TextureSpec texCubeArrayMipmapInt		(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA8I,	256,	256,	12,	9,	samplerNearestMipmap);
2940 	static const TextureSpec texCubeArrayMipmapUint		(TEXTURETYPE_CUBE_ARRAY,	GL_RGBA8UI,	256,	256,	12,	9,	samplerNearestMipmap);
2941 
2942 	static const TextureSpec texCubeArrayShadow			(TEXTURETYPE_CUBE_ARRAY,	GL_DEPTH_COMPONENT16,	256,	256,	12,	1,	samplerShadowNoMipmap);
2943 	static const TextureSpec texCubeArrayMipmapShadow	(TEXTURETYPE_CUBE_ARRAY,	GL_DEPTH_COMPONENT16,	256,	256,	12,	9,	samplerShadowMipmap);
2944 
2945 	// texture() cases
2946 	static const TexFuncCaseSpec textureCases[] =
2947 	{
2948 		//		  Name							Function			MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset		Format					EvalFunc				Flags
2949 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DFixed,				evalTexture2D,			VERTEX),
2950 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2D,			FRAGMENT),
2951 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DFloat,				evalTexture2D,			VERTEX),
2952 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2D,			FRAGMENT),
2953 		CASE_SPEC(isampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DInt,				evalTexture2D,			VERTEX),
2954 		CASE_SPEC(isampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2D,			FRAGMENT),
2955 		CASE_SPEC(usampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DUint,				evalTexture2D,			VERTEX),
2956 		CASE_SPEC(usampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2D,			FRAGMENT),
2957 
2958 		CASE_SPEC(sampler2d_bias_fixed,			FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DBias,		FRAGMENT),
2959 		CASE_SPEC(sampler2d_bias_float,			FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DBias,		FRAGMENT),
2960 		CASE_SPEC(isampler2d_bias,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DBias,		FRAGMENT),
2961 		CASE_SPEC(usampler2d_bias,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DBias,		FRAGMENT),
2962 
2963 		CASE_SPEC(samplercube_fixed,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeFixed,			evalTextureCube,		VERTEX),
2964 		CASE_SPEC(samplercube_fixed,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeMipmapFixed,		evalTextureCube,		FRAGMENT),
2965 		CASE_SPEC(samplercube_float,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeFloat,			evalTextureCube,		VERTEX),
2966 		CASE_SPEC(samplercube_float,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeMipmapFloat,		evalTextureCube,		FRAGMENT),
2967 		CASE_SPEC(isamplercube,					FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeInt,				evalTextureCube,		VERTEX),
2968 		CASE_SPEC(isamplercube,					FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeMipmapInt,		evalTextureCube,		FRAGMENT),
2969 		CASE_SPEC(usamplercube,					FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeUint,			evalTextureCube,		VERTEX),
2970 		CASE_SPEC(usamplercube,					FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeMipmapUint,		evalTextureCube,		FRAGMENT),
2971 
2972 		CASE_SPEC(samplercube_bias_fixed,		FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	texCubeMipmapFixed,		evalTextureCubeBias,	FRAGMENT),
2973 		CASE_SPEC(samplercube_bias_float,		FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	texCubeMipmapFloat,		evalTextureCubeBias,	FRAGMENT),
2974 		CASE_SPEC(isamplercube_bias,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	texCubeMipmapInt,		evalTextureCubeBias,	FRAGMENT),
2975 		CASE_SPEC(usamplercube_bias,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	texCubeMipmapUint,		evalTextureCubeBias,	FRAGMENT),
2976 
2977 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayFixed,		evalTexture2DArray,		VERTEX),
2978 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayMipmapFixed,	evalTexture2DArray,		FRAGMENT),
2979 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayFloat,		evalTexture2DArray,		VERTEX),
2980 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayMipmapFloat,	evalTexture2DArray,		FRAGMENT),
2981 		CASE_SPEC(isampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayInt,			evalTexture2DArray,		VERTEX),
2982 		CASE_SPEC(isampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayMipmapInt,	evalTexture2DArray,		FRAGMENT),
2983 		CASE_SPEC(usampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayUint,			evalTexture2DArray,		VERTEX),
2984 		CASE_SPEC(usampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayMipmapUint,	evalTexture2DArray,		FRAGMENT),
2985 
2986 		CASE_SPEC(sampler2darray_bias_fixed,	FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DArrayMipmapFixed,	evalTexture2DArrayBias,	FRAGMENT),
2987 		CASE_SPEC(sampler2darray_bias_float,	FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DArrayMipmapFloat,	evalTexture2DArrayBias,	FRAGMENT),
2988 		CASE_SPEC(isampler2darray_bias,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DArrayMipmapInt,	evalTexture2DArrayBias,	FRAGMENT),
2989 		CASE_SPEC(usampler2darray_bias,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DArrayMipmapUint,	evalTexture2DArrayBias,	FRAGMENT),
2990 
2991 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DFixed,				evalTexture3D,			VERTEX),
2992 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3D,			FRAGMENT),
2993 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DFloat,				evalTexture3D,			VERTEX),
2994 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3D,			FRAGMENT),
2995 		CASE_SPEC(isampler3d,					FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DInt,				evalTexture3D,			VERTEX),
2996 		CASE_SPEC(isampler3d,					FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3D,			FRAGMENT),
2997 		CASE_SPEC(usampler3d,					FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DUint,				evalTexture3D,			VERTEX),
2998 		CASE_SPEC(usampler3d,					FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3D,			FRAGMENT),
2999 
3000 		CASE_SPEC(sampler3d_bias_fixed,			FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	1.0f,	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3DBias,		FRAGMENT),
3001 		CASE_SPEC(sampler3d_bias_float,			FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	1.0f,	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DBias,		FRAGMENT),
3002 		CASE_SPEC(isampler3d_bias,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3DBias,		FRAGMENT),
3003 		CASE_SPEC(usampler3d_bias,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DBias,		FRAGMENT),
3004 
3005 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DShadow,			evalTexture2DShadow,			VERTEX),
3006 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadow,			FRAGMENT),
3007 		CASE_SPEC(sampler2dshadow_bias,			FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowBias,		FRAGMENT),
3008 
3009 		CASE_SPEC(samplercubeshadow,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  1.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeShadow,			evalTextureCubeShadow,			VERTEX),
3010 		CASE_SPEC(samplercubeshadow,			FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  1.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	texCubeMipmapShadow,	evalTextureCubeShadow,			FRAGMENT),
3011 		CASE_SPEC(samplercubeshadow_bias,		FUNCTION_TEXTURE,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  1.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	texCubeMipmapShadow,	evalTextureCubeShadowBias,		FRAGMENT),
3012 
3013 		CASE_SPEC(sampler2darrayshadow,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  1.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayShadow,		evalTexture2DArrayShadow,		VERTEX),
3014 		CASE_SPEC(sampler2darrayshadow,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  1.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayMipmapShadow,	evalTexture2DArrayShadow,		FRAGMENT)
3015 
3016 		// Not in spec.
3017 //		CASE_SPEC(sampler2darrayshadow_bias,	(FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  1.0f),	true,	-2.0f,	2.0f,	Vec2(0.0f),	Vec2(0.0f), false,	IVec3(0)),	tex2DArrayMipmapShadow,	evalTexture2DArrayShadowBias,	FRAGMENT)
3018 	};
3019 	createCaseGroup(this, "texture", "texture() Tests", textureCases, DE_LENGTH_OF_ARRAY(textureCases));
3020 
3021 	// textureOffset() cases
3022 	// \note _bias variants are not using mipmap thanks to wide allowed range for LOD computation
3023 	static const TexFuncCaseSpec textureOffsetCases[] =
3024 	{
3025 		//		  Name							Function			MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset				Format					EvalFunc						Flags
3026 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DFixed,				evalTexture2DOffset,			VERTEX),
3027 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFixed,		evalTexture2DOffset,			FRAGMENT),
3028 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DFloat,				evalTexture2DOffset,			VERTEX),
3029 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DOffset,			FRAGMENT),
3030 		CASE_SPEC(isampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DInt,				evalTexture2DOffset,			VERTEX),
3031 		CASE_SPEC(isampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapInt,			evalTexture2DOffset,			FRAGMENT),
3032 		CASE_SPEC(usampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DUint,				evalTexture2DOffset,			VERTEX),
3033 		CASE_SPEC(usampler2d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DOffset,			FRAGMENT),
3034 
3035 		CASE_SPEC(sampler2d_bias_fixed,			FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DFixed,				evalTexture2DOffsetBias,		FRAGMENT),
3036 		CASE_SPEC(sampler2d_bias_float,			FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DFloat,				evalTexture2DOffsetBias,		FRAGMENT),
3037 		CASE_SPEC(isampler2d_bias,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DInt,				evalTexture2DOffsetBias,		FRAGMENT),
3038 		CASE_SPEC(usampler2d_bias,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DUint,				evalTexture2DOffsetBias,		FRAGMENT),
3039 
3040 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayFixed,		evalTexture2DArrayOffset,		VERTEX),
3041 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DArrayMipmapFixed,	evalTexture2DArrayOffset,		FRAGMENT),
3042 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayFloat,		evalTexture2DArrayOffset,		VERTEX),
3043 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DArrayMipmapFloat,	evalTexture2DArrayOffset,		FRAGMENT),
3044 		CASE_SPEC(isampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayInt,			evalTexture2DArrayOffset,		VERTEX),
3045 		CASE_SPEC(isampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DArrayMipmapInt,	evalTexture2DArrayOffset,		FRAGMENT),
3046 		CASE_SPEC(usampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayUint,			evalTexture2DArrayOffset,		VERTEX),
3047 		CASE_SPEC(usampler2darray,				FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DArrayMipmapUint,	evalTexture2DArrayOffset,		FRAGMENT),
3048 
3049 		CASE_SPEC(sampler2darray_bias_fixed,	FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayFixed,		evalTexture2DArrayOffsetBias,	FRAGMENT),
3050 		CASE_SPEC(sampler2darray_bias_float,	FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DArrayFloat,		evalTexture2DArrayOffsetBias,	FRAGMENT),
3051 		CASE_SPEC(isampler2darray_bias,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayInt,			evalTexture2DArrayOffsetBias,	FRAGMENT),
3052 		CASE_SPEC(usampler2darray_bias,			FUNCTION_TEXTURE,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DArrayUint,			evalTexture2DArrayOffsetBias,	FRAGMENT),
3053 
3054 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DFixed,				evalTexture3DOffset,			VERTEX),
3055 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, 3, -8),	tex3DMipmapFixed,		evalTexture3DOffset,			FRAGMENT),
3056 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(3, -8, 7),	tex3DFloat,				evalTexture3DOffset,			VERTEX),
3057 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DMipmapFloat,		evalTexture3DOffset,			FRAGMENT),
3058 		CASE_SPEC(isampler3d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, 3, -8),	tex3DInt,				evalTexture3DOffset,			VERTEX),
3059 		CASE_SPEC(isampler3d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(3, -8, 7),	tex3DMipmapInt,			evalTexture3DOffset,			FRAGMENT),
3060 		CASE_SPEC(usampler3d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DUint,				evalTexture3DOffset,			VERTEX),
3061 		CASE_SPEC(usampler3d,					FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, 3, -8),	tex3DMipmapUint,		evalTexture3DOffset,			FRAGMENT),
3062 
3063 		CASE_SPEC(sampler3d_bias_fixed,			FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	1.0f,	true,	IVec3(-8, 7, 3),	tex3DFixed,				evalTexture3DOffsetBias,		FRAGMENT),
3064 		CASE_SPEC(sampler3d_bias_float,			FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	1.0f,	true,	IVec3(7, 3, -8),	tex3DFloat,				evalTexture3DOffsetBias,		FRAGMENT),
3065 		CASE_SPEC(isampler3d_bias,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(3, -8, 7),	tex3DInt,				evalTexture3DOffsetBias,		FRAGMENT),
3066 		CASE_SPEC(usampler3d_bias,				FUNCTION_TEXTURE,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 3),	tex3DUint,				evalTexture3DOffsetBias,		FRAGMENT),
3067 
3068 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DShadow,			evalTexture2DShadowOffset,		VERTEX),
3069 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapShadow,		evalTexture2DShadowOffset,		FRAGMENT),
3070 		CASE_SPEC(sampler2dshadow_bias,			FUNCTION_TEXTURE,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DShadow,			evalTexture2DShadowOffsetBias,	FRAGMENT)
3071 	};
3072 	createCaseGroup(this, "textureoffset", "textureOffset() Tests", textureOffsetCases, DE_LENGTH_OF_ARRAY(textureOffsetCases));
3073 
3074 	// textureProj() cases
3075 	// \note Currently uses constant divider!
3076 	static const TexFuncCaseSpec textureProjCases[] =
3077 	{
3078 		//		  Name							Function				MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset		Format					EvalFunc				Flags
3079 		CASE_SPEC(sampler2d_vec3_fixed,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DFixed,				evalTexture2DProj3,		VERTEX),
3080 		CASE_SPEC(sampler2d_vec3_fixed,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProj3,		FRAGMENT),
3081 		CASE_SPEC(sampler2d_vec3_float,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DFloat,				evalTexture2DProj3,		VERTEX),
3082 		CASE_SPEC(sampler2d_vec3_float,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProj3,		FRAGMENT),
3083 		CASE_SPEC(isampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DInt,				evalTexture2DProj3,		VERTEX),
3084 		CASE_SPEC(isampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProj3,		FRAGMENT),
3085 		CASE_SPEC(usampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DUint,				evalTexture2DProj3,		VERTEX),
3086 		CASE_SPEC(usampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProj3,		FRAGMENT),
3087 
3088 		CASE_SPEC(sampler2d_vec3_bias_fixed,	FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProj3Bias,	FRAGMENT),
3089 		CASE_SPEC(sampler2d_vec3_bias_float,	FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProj3Bias,	FRAGMENT),
3090 		CASE_SPEC(isampler2d_vec3_bias,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProj3Bias,	FRAGMENT),
3091 		CASE_SPEC(usampler2d_vec3_bias,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProj3Bias,	FRAGMENT),
3092 
3093 		CASE_SPEC(sampler2d_vec4_fixed,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DFixed,				evalTexture2DProj,		VERTEX),
3094 		CASE_SPEC(sampler2d_vec4_fixed,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProj,		FRAGMENT),
3095 		CASE_SPEC(sampler2d_vec4_float,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DFloat,				evalTexture2DProj,		VERTEX),
3096 		CASE_SPEC(sampler2d_vec4_float,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProj,		FRAGMENT),
3097 		CASE_SPEC(isampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DInt,				evalTexture2DProj,		VERTEX),
3098 		CASE_SPEC(isampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProj,		FRAGMENT),
3099 		CASE_SPEC(usampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DUint,				evalTexture2DProj,		VERTEX),
3100 		CASE_SPEC(usampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProj,		FRAGMENT),
3101 
3102 		CASE_SPEC(sampler2d_vec4_bias_fixed,	FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProjBias,	FRAGMENT),
3103 		CASE_SPEC(sampler2d_vec4_bias_float,	FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProjBias,	FRAGMENT),
3104 		CASE_SPEC(isampler2d_vec4_bias,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProjBias,	FRAGMENT),
3105 		CASE_SPEC(usampler2d_vec4_bias,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProjBias,	FRAGMENT),
3106 
3107 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DFixed,				evalTexture3DProj,		VERTEX),
3108 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3DProj,		FRAGMENT),
3109 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DFloat,				evalTexture3DProj,		VERTEX),
3110 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DProj,		FRAGMENT),
3111 		CASE_SPEC(isampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DInt,				evalTexture3DProj,		VERTEX),
3112 		CASE_SPEC(isampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3DProj,		FRAGMENT),
3113 		CASE_SPEC(usampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DUint,				evalTexture3DProj,		VERTEX),
3114 		CASE_SPEC(usampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DProj,		FRAGMENT),
3115 
3116 		CASE_SPEC(sampler3d_bias_fixed,			FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	1.0f,	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3DProjBias,	FRAGMENT),
3117 		CASE_SPEC(sampler3d_bias_float,			FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	1.0f,	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DProjBias,	FRAGMENT),
3118 		CASE_SPEC(isampler3d_bias,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3DProjBias,	FRAGMENT),
3119 		CASE_SPEC(usampler3d_bias,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DProjBias,	FRAGMENT),
3120 
3121 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTUREPROJ,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DShadow,			evalTexture2DShadowProj,		VERTEX),
3122 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTUREPROJ,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowProj,		FRAGMENT),
3123 		CASE_SPEC(sampler2dshadow_bias,			FUNCTION_TEXTUREPROJ,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	true,	-2.0f,	2.0f,	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowProjBias,	FRAGMENT)
3124 	};
3125 	createCaseGroup(this, "textureproj", "textureProj() Tests", textureProjCases, DE_LENGTH_OF_ARRAY(textureProjCases));
3126 
3127 	// textureProjOffset() cases
3128 	// \note Currently uses constant divider!
3129 	static const TexFuncCaseSpec textureProjOffsetCases[] =
3130 	{
3131 		//		  Name							Function				MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset				Format					EvalFunc						Flags
3132 		CASE_SPEC(sampler2d_vec3_fixed,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DFixed,				evalTexture2DProj3Offset,		VERTEX),
3133 		CASE_SPEC(sampler2d_vec3_fixed,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFixed,		evalTexture2DProj3Offset,		FRAGMENT),
3134 		CASE_SPEC(sampler2d_vec3_float,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DFloat,				evalTexture2DProj3Offset,		VERTEX),
3135 		CASE_SPEC(sampler2d_vec3_float,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DProj3Offset,		FRAGMENT),
3136 		CASE_SPEC(isampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DInt,				evalTexture2DProj3Offset,		VERTEX),
3137 		CASE_SPEC(isampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapInt,			evalTexture2DProj3Offset,		FRAGMENT),
3138 		CASE_SPEC(usampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DUint,				evalTexture2DProj3Offset,		VERTEX),
3139 		CASE_SPEC(usampler2d_vec3,				FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DProj3Offset,		FRAGMENT),
3140 
3141 		CASE_SPEC(sampler2d_vec3_bias_fixed,	FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DFixed,				evalTexture2DProj3OffsetBias,	FRAGMENT),
3142 		CASE_SPEC(sampler2d_vec3_bias_float,	FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DFloat,				evalTexture2DProj3OffsetBias,	FRAGMENT),
3143 		CASE_SPEC(isampler2d_vec3_bias,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DInt,				evalTexture2DProj3OffsetBias,	FRAGMENT),
3144 		CASE_SPEC(usampler2d_vec3_bias,			FUNCTION_TEXTUREPROJ3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DUint,				evalTexture2DProj3OffsetBias,	FRAGMENT),
3145 
3146 		CASE_SPEC(sampler2d_vec4_fixed,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DFixed,				evalTexture2DProjOffset,		VERTEX),
3147 		CASE_SPEC(sampler2d_vec4_fixed,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFixed,		evalTexture2DProjOffset,		FRAGMENT),
3148 		CASE_SPEC(sampler2d_vec4_float,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DFloat,				evalTexture2DProjOffset,		VERTEX),
3149 		CASE_SPEC(sampler2d_vec4_float,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DProjOffset,		FRAGMENT),
3150 		CASE_SPEC(isampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DInt,				evalTexture2DProjOffset,		VERTEX),
3151 		CASE_SPEC(isampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapInt,			evalTexture2DProjOffset,		FRAGMENT),
3152 		CASE_SPEC(usampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DUint,				evalTexture2DProjOffset,		VERTEX),
3153 		CASE_SPEC(usampler2d_vec4,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DProjOffset,		FRAGMENT),
3154 
3155 		CASE_SPEC(sampler2d_vec4_bias_fixed,	FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DFixed,				evalTexture2DProjOffsetBias,	FRAGMENT),
3156 		CASE_SPEC(sampler2d_vec4_bias_float,	FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DFloat,				evalTexture2DProjOffsetBias,	FRAGMENT),
3157 		CASE_SPEC(isampler2d_vec4_bias,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DInt,				evalTexture2DProjOffsetBias,	FRAGMENT),
3158 		CASE_SPEC(usampler2d_vec4_bias,			FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	true,	-2.0f,	2.0f,	true,	IVec3(7, -8, 0),	tex2DUint,				evalTexture2DProjOffsetBias,	FRAGMENT),
3159 
3160 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DFixed,				evalTexture3DProjOffset,		VERTEX),
3161 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, 3, -8),	tex3DMipmapFixed,		evalTexture3DProjOffset,		FRAGMENT),
3162 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(3, -8, 7),	tex3DFloat,				evalTexture3DProjOffset,		VERTEX),
3163 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DMipmapFloat,		evalTexture3DProjOffset,		FRAGMENT),
3164 		CASE_SPEC(isampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, 3, -8),	tex3DInt,				evalTexture3DProjOffset,		VERTEX),
3165 		CASE_SPEC(isampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(3, -8, 7),	tex3DMipmapInt,			evalTexture3DProjOffset,		FRAGMENT),
3166 		CASE_SPEC(usampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DUint,				evalTexture3DProjOffset,		VERTEX),
3167 		CASE_SPEC(usampler3d,					FUNCTION_TEXTUREPROJ,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  2.0f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, 3, -8),	tex3DMipmapUint,		evalTexture3DProjOffset,		FRAGMENT),
3168 
3169 		CASE_SPEC(sampler3d_bias_fixed,			FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 3),	tex3DFixed,				evalTexture3DProjOffsetBias,	FRAGMENT),
3170 		CASE_SPEC(sampler3d_bias_float,			FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	2.0f,	true,	IVec3(7, 3, -8),	tex3DFloat,				evalTexture3DProjOffsetBias,	FRAGMENT),
3171 		CASE_SPEC(isampler3d_bias,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	2.0f,	true,	IVec3(3, -8, 7),	tex3DInt,				evalTexture3DProjOffsetBias,	FRAGMENT),
3172 		CASE_SPEC(usampler3d_bias,				FUNCTION_TEXTUREPROJ,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 3),	tex3DUint,				evalTexture3DProjOffsetBias,	FRAGMENT),
3173 
3174 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTUREPROJ,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DShadow,			evalTexture2DShadowProjOffset,		VERTEX),
3175 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTUREPROJ,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	false,	0.0f,	0.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapShadow,		evalTexture2DShadowProjOffset,		FRAGMENT),
3176 		CASE_SPEC(sampler2dshadow_bias,			FUNCTION_TEXTUREPROJ,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	true,	-2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DShadow,			evalTexture2DShadowProjOffsetBias,	FRAGMENT)
3177 	};
3178 	createCaseGroup(this, "textureprojoffset", "textureOffsetProj() Tests", textureProjOffsetCases, DE_LENGTH_OF_ARRAY(textureProjOffsetCases));
3179 
3180 	// textureLod() cases
3181 	static const TexFuncCaseSpec textureLodCases[] =
3182 	{
3183 		//		  Name							Function				MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset		Format					EvalFunc				Flags
3184 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DLod,		BOTH),
3185 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DLod,		BOTH),
3186 		CASE_SPEC(isampler2d,					FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DLod,		BOTH),
3187 		CASE_SPEC(usampler2d,					FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DLod,		BOTH),
3188 
3189 		CASE_SPEC(samplercube_fixed,			FUNCTION_TEXTURELOD,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	texCubeMipmapFixed,		evalTextureCubeLod,		BOTH),
3190 		CASE_SPEC(samplercube_float,			FUNCTION_TEXTURELOD,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	texCubeMipmapFloat,		evalTextureCubeLod,		BOTH),
3191 		CASE_SPEC(isamplercube,					FUNCTION_TEXTURELOD,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	texCubeMipmapInt,		evalTextureCubeLod,		BOTH),
3192 		CASE_SPEC(usamplercube,					FUNCTION_TEXTURELOD,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	texCubeMipmapUint,		evalTextureCubeLod,		BOTH),
3193 
3194 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	false,	IVec3(0),	tex2DArrayMipmapFixed,	evalTexture2DArrayLod,	BOTH),
3195 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	false,	IVec3(0),	tex2DArrayMipmapFloat,	evalTexture2DArrayLod,	BOTH),
3196 		CASE_SPEC(isampler2darray,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	false,	IVec3(0),	tex2DArrayMipmapInt,	evalTexture2DArrayLod,	BOTH),
3197 		CASE_SPEC(usampler2darray,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	false,	IVec3(0),	tex2DArrayMipmapUint,	evalTexture2DArrayLod,	BOTH),
3198 
3199 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3DLod,		BOTH),
3200 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DLod,		BOTH),
3201 		CASE_SPEC(isampler3d,					FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3DLod,		BOTH),
3202 		CASE_SPEC(usampler3d,					FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DLod,		BOTH),
3203 
3204 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowLod,	BOTH)
3205 	};
3206 	createCaseGroup(this, "texturelod", "textureLod() Tests", textureLodCases, DE_LENGTH_OF_ARRAY(textureLodCases));
3207 
3208 	// textureLodOffset() cases
3209 	static const TexFuncCaseSpec textureLodOffsetCases[] =
3210 	{
3211 		//		  Name							Function				MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset				Format					EvalFunc						Flags
3212 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapFixed,		evalTexture2DLodOffset,			BOTH),
3213 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DLodOffset,			BOTH),
3214 		CASE_SPEC(isampler2d,					FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapInt,			evalTexture2DLodOffset,			BOTH),
3215 		CASE_SPEC(usampler2d,					FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DLodOffset,			BOTH),
3216 
3217 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayMipmapFixed,	evalTexture2DArrayLodOffset,	BOTH),
3218 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	true,	IVec3(7, -8, 0),	tex2DArrayMipmapFloat,	evalTexture2DArrayLodOffset,	BOTH),
3219 		CASE_SPEC(isampler2darray,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayMipmapInt,	evalTexture2DArrayLodOffset,	BOTH),
3220 		CASE_SPEC(usampler2darray,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	false,	-1.0f,	8.0f,	true,	IVec3(7, -8, 0),	tex2DArrayMipmapUint,	evalTexture2DArrayLodOffset,	BOTH),
3221 
3222 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	true,	IVec3(-8, 7, 3),	tex3DMipmapFixed,		evalTexture3DLodOffset,			BOTH),
3223 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	true,	IVec3(7, 3, -8),	tex3DMipmapFloat,		evalTexture3DLodOffset,			BOTH),
3224 		CASE_SPEC(isampler3d,					FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	true,	IVec3(3, -8, 7),	tex3DMipmapInt,			evalTexture3DLodOffset,			BOTH),
3225 		CASE_SPEC(usampler3d,					FUNCTION_TEXTURELOD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	false,	-1.0f,	7.0f,	true,	IVec3(-8, 7, 3),	tex3DMipmapUint,		evalTexture3DLodOffset,			BOTH),
3226 
3227 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTURELOD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapShadow,		evalTexture2DShadowLodOffset,	BOTH)
3228 	};
3229 	createCaseGroup(this, "texturelodoffset", "textureLodOffset() Tests", textureLodOffsetCases, DE_LENGTH_OF_ARRAY(textureLodOffsetCases));
3230 
3231 	// textureProjLod() cases
3232 	static const TexFuncCaseSpec textureProjLodCases[] =
3233 	{
3234 		//		  Name							Function					MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset		Format					EvalFunc					Flags
3235 		CASE_SPEC(sampler2d_vec3_fixed,			FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProjLod3,		BOTH),
3236 		CASE_SPEC(sampler2d_vec3_float,			FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProjLod3,		BOTH),
3237 		CASE_SPEC(isampler2d_vec3,				FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProjLod3,		BOTH),
3238 		CASE_SPEC(usampler2d_vec3,				FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProjLod3,		BOTH),
3239 
3240 		CASE_SPEC(sampler2d_vec4_fixed,			FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProjLod,		BOTH),
3241 		CASE_SPEC(sampler2d_vec4_float,			FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProjLod,		BOTH),
3242 		CASE_SPEC(isampler2d_vec4,				FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProjLod,		BOTH),
3243 		CASE_SPEC(usampler2d_vec4,				FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProjLod,		BOTH),
3244 
3245 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3DProjLod,		BOTH),
3246 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DProjLod,		BOTH),
3247 		CASE_SPEC(isampler3d,					FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3DProjLod,		BOTH),
3248 		CASE_SPEC(usampler3d,					FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DProjLod,		BOTH),
3249 
3250 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTUREPROJLOD,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	false,	-1.0f,	9.0f,	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowProjLod,	BOTH)
3251 	};
3252 	createCaseGroup(this, "textureprojlod", "textureProjLod() Tests", textureProjLodCases, DE_LENGTH_OF_ARRAY(textureProjLodCases));
3253 
3254 	// textureProjLodOffset() cases
3255 	static const TexFuncCaseSpec textureProjLodOffsetCases[] =
3256 	{
3257 		//		  Name							Function					MinCoord							MaxCoord							Bias?	MinLod	MaxLod	Offset?	Offset				Format					EvalFunc								Flags
3258 		CASE_SPEC(sampler2d_vec3_fixed,			FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapFixed,		evalTexture2DProjLod3Offset,	BOTH),
3259 		CASE_SPEC(sampler2d_vec3_float,			FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DProjLod3Offset,	BOTH),
3260 		CASE_SPEC(isampler2d_vec3,				FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapInt,			evalTexture2DProjLod3Offset,	BOTH),
3261 		CASE_SPEC(usampler2d_vec3,				FUNCTION_TEXTUREPROJLOD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	false,	-1.0f,	9.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DProjLod3Offset,	BOTH),
3262 
3263 		CASE_SPEC(sampler2d_vec4_fixed,			FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapFixed,		evalTexture2DProjLodOffset,		BOTH),
3264 		CASE_SPEC(sampler2d_vec4_float,			FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DProjLodOffset,		BOTH),
3265 		CASE_SPEC(isampler2d_vec4,				FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapInt,			evalTexture2DProjLodOffset,		BOTH),
3266 		CASE_SPEC(usampler2d_vec4,				FUNCTION_TEXTUREPROJLOD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	false,	-1.0f,	9.0f,	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DProjLodOffset,		BOTH),
3267 
3268 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	true,	IVec3(-8, 7, 3),	tex3DMipmapFixed,		evalTexture3DProjLodOffset,		BOTH),
3269 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	true,	IVec3(7, 3, -8),	tex3DMipmapFloat,		evalTexture3DProjLodOffset,		BOTH),
3270 		CASE_SPEC(isampler3d,					FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	true,	IVec3(3, -8, 7),	tex3DMipmapInt,			evalTexture3DProjLodOffset,		BOTH),
3271 		CASE_SPEC(usampler3d,					FUNCTION_TEXTUREPROJLOD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	false,	-1.0f,	7.0f,	true,	IVec3(-8, 7, 3),	tex3DMipmapUint,		evalTexture3DProjLodOffset,		BOTH),
3272 
3273 		CASE_SPEC(sampler2dshadow,				FUNCTION_TEXTUREPROJLOD,	Vec4( 0.2f, 0.6f,  0.0f,  1.5f),	Vec4(-2.25f, -3.45f, 1.5f,  1.5f),	false,	-1.0f,	9.0f,	true,	IVec3(-8, 7, 0),	tex2DMipmapShadow,		evalTexture2DShadowProjLodOffset,	BOTH)
3274 	};
3275 	createCaseGroup(this, "textureprojlodoffset", "textureProjLodOffset() Tests", textureProjLodOffsetCases, DE_LENGTH_OF_ARRAY(textureProjLodOffsetCases));
3276 
3277 	// textureGrad() cases
3278 	// \note Only one of dudx, dudy, dvdx, dvdy is non-zero since spec allows approximating p from derivates by various methods.
3279 	static const TexFuncCaseSpec textureGradCases[] =
3280 	{
3281 		//		  Name							Function				MinCoord							MaxCoord							MinDx						MaxDx						MinDy						MaxDy						Offset?	Offset		Format					EvalFunc				Flags
3282 		GRAD_CASE_SPEC(sampler2d_fixed,			FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DGrad,		BOTH),
3283 		GRAD_CASE_SPEC(sampler2d_float,			FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DGrad,		BOTH),
3284 		GRAD_CASE_SPEC(isampler2d,				FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DGrad,		BOTH),
3285 		GRAD_CASE_SPEC(usampler2d,				FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DGrad,		BOTH),
3286 
3287 		GRAD_CASE_SPEC(samplercube_fixed,		FUNCTION_TEXTUREGRAD,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	texCubeMipmapFixed,		evalTextureCubeGrad,	BOTH),
3288 		GRAD_CASE_SPEC(samplercube_float,		FUNCTION_TEXTUREGRAD,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	texCubeMipmapFloat,		evalTextureCubeGrad,	BOTH),
3289 		GRAD_CASE_SPEC(isamplercube,			FUNCTION_TEXTUREGRAD,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	false,	IVec3(0),	texCubeMipmapInt,		evalTextureCubeGrad,	BOTH),
3290 		GRAD_CASE_SPEC(usamplercube,			FUNCTION_TEXTUREGRAD,	Vec4(-1.0f, -1.0f, -1.01f,  0.0f),	Vec4( 1.0f,  1.0f, -1.01f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	false,	IVec3(0),	texCubeMipmapUint,		evalTextureCubeGrad,	BOTH),
3291 
3292 		GRAD_CASE_SPEC(sampler2darray_fixed,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DArrayMipmapFixed,	evalTexture2DArrayGrad,	BOTH),
3293 		GRAD_CASE_SPEC(sampler2darray_float,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DArrayMipmapFloat,	evalTexture2DArrayGrad,	BOTH),
3294 		GRAD_CASE_SPEC(isampler2darray,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DArrayMipmapInt,	evalTexture2DArrayGrad,	BOTH),
3295 		GRAD_CASE_SPEC(usampler2darray,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	false,	IVec3(0),	tex2DArrayMipmapUint,	evalTexture2DArrayGrad,	BOTH),
3296 
3297 		GRAD_CASE_SPEC(sampler3d_fixed,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3DGrad,		BOTH),
3298 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DGrad,		VERTEX),
3299 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.2f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DGrad,		FRAGMENT),
3300 		GRAD_CASE_SPEC(isampler3d,				FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3DGrad,		BOTH),
3301 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DGrad,		VERTEX),
3302 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f, -0.2f),	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DGrad,		FRAGMENT),
3303 
3304 		GRAD_CASE_SPEC(sampler2dshadow,			FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowGrad,		BOTH),
3305 		GRAD_CASE_SPEC(samplercubeshadow,		FUNCTION_TEXTUREGRAD,	Vec4(-1.0f, -1.0f,  1.01f,  0.0f),	Vec4( 1.0f,  1.0f,  1.01f,  1.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	texCubeMipmapShadow,	evalTextureCubeShadowGrad,		BOTH),
3306 		GRAD_CASE_SPEC(sampler2darrayshadow,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  1.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DArrayMipmapShadow,	evalTexture2DArrayShadowGrad,	VERTEX),
3307 		GRAD_CASE_SPEC(sampler2darrayshadow,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  1.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	false,	IVec3(0),	tex2DArrayMipmapShadow,	evalTexture2DArrayShadowGrad,	FRAGMENT)
3308 	};
3309 	createCaseGroup(this, "texturegrad", "textureGrad() Tests", textureGradCases, DE_LENGTH_OF_ARRAY(textureGradCases));
3310 
3311 	// textureGradOffset() cases
3312 	static const TexFuncCaseSpec textureGradOffsetCases[] =
3313 	{
3314 		//		  Name							Function				MinCoord							MaxCoord							MinDx						MaxDx						MinDy						MaxDy						Offset?	Offset				Format					EvalFunc							Flags
3315 		GRAD_CASE_SPEC(sampler2d_fixed,			FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapFixed,		evalTexture2DGradOffset,			BOTH),
3316 		GRAD_CASE_SPEC(sampler2d_float,			FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DGradOffset,			BOTH),
3317 		GRAD_CASE_SPEC(isampler2d,				FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapInt,			evalTexture2DGradOffset,			BOTH),
3318 		GRAD_CASE_SPEC(usampler2d,				FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DGradOffset,			BOTH),
3319 
3320 		GRAD_CASE_SPEC(sampler2darray_fixed,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DArrayMipmapFixed,	evalTexture2DArrayGradOffset,		BOTH),
3321 		GRAD_CASE_SPEC(sampler2darray_float,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DArrayMipmapFloat,	evalTexture2DArrayGradOffset,		BOTH),
3322 		GRAD_CASE_SPEC(isampler2darray,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DArrayMipmapInt,	evalTexture2DArrayGradOffset,		BOTH),
3323 		GRAD_CASE_SPEC(usampler2darray,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DArrayMipmapUint,	evalTexture2DArrayGradOffset,		BOTH),
3324 
3325 		GRAD_CASE_SPEC(sampler3d_fixed,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 3),	tex3DMipmapFixed,		evalTexture3DGradOffset,			BOTH),
3326 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(7, 3, -8),	tex3DMipmapFloat,		evalTexture3DGradOffset,			VERTEX),
3327 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.2f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(3, -8, 7),	tex3DMipmapFloat,		evalTexture3DGradOffset,			FRAGMENT),
3328 		GRAD_CASE_SPEC(isampler3d,				FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 3),	tex3DMipmapInt,			evalTexture3DGradOffset,			BOTH),
3329 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	true,	IVec3(7, 3, -8),	tex3DMipmapUint,		evalTexture3DGradOffset,			VERTEX),
3330 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -1.4f,  0.1f,  0.0f),	Vec4( 1.5f,  2.3f,  2.3f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f, -0.2f),	true,	IVec3(3, -8, 7),	tex3DMipmapUint,		evalTexture3DGradOffset,			FRAGMENT),
3331 
3332 		GRAD_CASE_SPEC(sampler2dshadow,			FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapShadow,		evalTexture2DShadowGradOffset,		VERTEX),
3333 		GRAD_CASE_SPEC(sampler2dshadow,			FUNCTION_TEXTUREGRAD,	Vec4(-0.2f, -0.4f,  0.0f,  0.0f),	Vec4( 1.5f,  2.3f,  1.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapShadow,		evalTexture2DShadowGradOffset,		FRAGMENT),
3334 		GRAD_CASE_SPEC(sampler2darrayshadow,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  1.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DArrayMipmapShadow,	evalTexture2DArrayShadowGradOffset,	VERTEX),
3335 		GRAD_CASE_SPEC(sampler2darrayshadow,	FUNCTION_TEXTUREGRAD,	Vec4(-1.2f, -0.4f,  -0.5f,  0.0f),	Vec4( 1.5f,  2.3f,  3.5f,  1.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DArrayMipmapShadow,	evalTexture2DArrayShadowGradOffset,	FRAGMENT)
3336 	};
3337 	createCaseGroup(this, "texturegradoffset", "textureGradOffset() Tests", textureGradOffsetCases, DE_LENGTH_OF_ARRAY(textureGradOffsetCases));
3338 
3339 	// textureProjGrad() cases
3340 	static const TexFuncCaseSpec textureProjGradCases[] =
3341 	{
3342 		//		  Name							Function					MinCoord							MaxCoord							MinDx						MaxDx						MinDy						MaxDy						Offset?	Offset		Format					EvalFunc					Flags
3343 		GRAD_CASE_SPEC(sampler2d_vec3_fixed,	FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProjGrad3,		BOTH),
3344 		GRAD_CASE_SPEC(sampler2d_vec3_float,	FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProjGrad3,		BOTH),
3345 		GRAD_CASE_SPEC(isampler2d_vec3,			FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProjGrad3,		BOTH),
3346 		GRAD_CASE_SPEC(usampler2d_vec3,			FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProjGrad3,		BOTH),
3347 
3348 		GRAD_CASE_SPEC(sampler2d_vec4_fixed,	FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapFixed,		evalTexture2DProjGrad,		BOTH),
3349 		GRAD_CASE_SPEC(sampler2d_vec4_float,	FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapFloat,		evalTexture2DProjGrad,		BOTH),
3350 		GRAD_CASE_SPEC(isampler2d_vec4,			FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapInt,			evalTexture2DProjGrad,		BOTH),
3351 		GRAD_CASE_SPEC(usampler2d_vec4,			FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	false,	IVec3(0),	tex2DMipmapUint,		evalTexture2DProjGrad,		BOTH),
3352 
3353 		GRAD_CASE_SPEC(sampler3d_fixed,			FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapFixed,		evalTexture3DProjGrad,		BOTH),
3354 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DProjGrad,		VERTEX),
3355 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.2f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapFloat,		evalTexture3DProjGrad,		FRAGMENT),
3356 		GRAD_CASE_SPEC(isampler3d,				FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	false,	IVec3(0),	tex3DMipmapInt,			evalTexture3DProjGrad,		BOTH),
3357 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DProjGrad,		VERTEX),
3358 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f, -0.2f),	false,	IVec3(0),	tex3DMipmapUint,		evalTexture3DProjGrad,		FRAGMENT),
3359 
3360 		GRAD_CASE_SPEC(sampler2dshadow,			FUNCTION_TEXTUREPROJGRAD,	Vec4( 0.2f, 0.6f,  0.0f,  -1.5f),	Vec4(-2.25f, -3.45f, -1.5f, -1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowProjGrad,	VERTEX),
3361 		GRAD_CASE_SPEC(sampler2dshadow,			FUNCTION_TEXTUREPROJGRAD,	Vec4( 0.2f, 0.6f,  0.0f,  -1.5f),	Vec4(-2.25f, -3.45f, -1.5f, -1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	false,	IVec3(0),	tex2DMipmapShadow,		evalTexture2DShadowProjGrad,	FRAGMENT)
3362 	};
3363 	createCaseGroup(this, "textureprojgrad", "textureProjGrad() Tests", textureProjGradCases, DE_LENGTH_OF_ARRAY(textureProjGradCases));
3364 
3365 	// textureProjGradOffset() cases
3366 	static const TexFuncCaseSpec textureProjGradOffsetCases[] =
3367 	{
3368 		//		  Name							Function					MinCoord							MaxCoord							MinDx						MaxDx						MinDy						MaxDy						Offset?	Offset				Format					EvalFunc							Flags
3369 		GRAD_CASE_SPEC(sampler2d_vec3_fixed,	FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapFixed,		evalTexture2DProjGrad3Offset,		BOTH),
3370 		GRAD_CASE_SPEC(sampler2d_vec3_float,	FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DProjGrad3Offset,		BOTH),
3371 		GRAD_CASE_SPEC(isampler2d_vec3,			FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapInt,			evalTexture2DProjGrad3Offset,		BOTH),
3372 		GRAD_CASE_SPEC(usampler2d_vec3,			FUNCTION_TEXTUREPROJGRAD3,	Vec4(-0.3f, -0.6f,  1.5f,  0.0f),	Vec4(2.25f, 3.45f,  1.5f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DProjGrad3Offset,		BOTH),
3373 
3374 		GRAD_CASE_SPEC(sampler2d_vec4_fixed,	FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapFixed,		evalTexture2DProjGradOffset,		BOTH),
3375 		GRAD_CASE_SPEC(sampler2d_vec4_float,	FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapFloat,		evalTexture2DProjGradOffset,		BOTH),
3376 		GRAD_CASE_SPEC(isampler2d_vec4,			FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapInt,			evalTexture2DProjGradOffset,		BOTH),
3377 		GRAD_CASE_SPEC(usampler2d_vec4,			FUNCTION_TEXTUREPROJGRAD,	Vec4(-0.3f, -0.6f,  0.0f,  1.5f),	Vec4(2.25f, 3.45f,  0.0f,  1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapUint,		evalTexture2DProjGradOffset,		BOTH),
3378 
3379 		GRAD_CASE_SPEC(sampler3d_fixed,			FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 3),	tex3DMipmapFixed,		evalTexture3DProjGradOffset,		BOTH),
3380 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(7, 3, -8),	tex3DMipmapFloat,		evalTexture3DProjGradOffset,		VERTEX),
3381 		GRAD_CASE_SPEC(sampler3d_float,			FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.2f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(3, -8, 7),	tex3DMipmapFloat,		evalTexture3DProjGradOffset,		FRAGMENT),
3382 		GRAD_CASE_SPEC(isampler3d,				FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3(-0.2f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 3),	tex3DMipmapInt,			evalTexture3DProjGradOffset,		BOTH),
3383 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.2f,  0.0f),	true,	IVec3(7, 3, -8),	tex3DMipmapUint,		evalTexture3DProjGradOffset,		VERTEX),
3384 		GRAD_CASE_SPEC(usampler3d,				FUNCTION_TEXTUREPROJGRAD,	Vec4(0.9f, 1.05f, -0.08f, -0.75f),	Vec4(-1.13f, -1.7f, -1.7f, -0.75f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f, -0.2f),	true,	IVec3(3, -8, 7),	tex3DMipmapUint,		evalTexture3DProjGradOffset,		FRAGMENT),
3385 
3386 		GRAD_CASE_SPEC(sampler2dshadow,			FUNCTION_TEXTUREPROJGRAD,	Vec4( 0.2f, 0.6f,  0.0f,  -1.5f),	Vec4(-2.25f, -3.45f, -1.5f, -1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.2f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	true,	IVec3(-8, 7, 0),	tex2DMipmapShadow,		evalTexture2DShadowProjGradOffset,	VERTEX),
3387 		GRAD_CASE_SPEC(sampler2dshadow,			FUNCTION_TEXTUREPROJGRAD,	Vec4( 0.2f, 0.6f,  0.0f,  -1.5f),	Vec4(-2.25f, -3.45f, -1.5f, -1.5f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f,  0.0f,  0.0f),	Vec3( 0.0f, -0.2f,  0.0f),	true,	IVec3(7, -8, 0),	tex2DMipmapShadow,		evalTexture2DShadowProjGradOffset,	FRAGMENT)
3388 	};
3389 	createCaseGroup(this, "textureprojgradoffset", "textureProjGradOffset() Tests", textureProjGradOffsetCases, DE_LENGTH_OF_ARRAY(textureProjGradOffsetCases));
3390 
3391 	// texelFetch() cases
3392 	// \note Level is constant across quad
3393 	static const TexFuncCaseSpec texelFetchCases[] =
3394 	{
3395 		//		  Name							Function				MinCoord							MaxCoord						Bias?	MinLod	MaxLod	Offset?	Offset		Format						EvalFunc				Flags
3396 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4(255.9f, 255.9f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DTexelFetchFixed,		evalTexelFetch2D,		BOTH),
3397 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4(127.9f, 127.9f,  0.0f,  0.0f),	false,	1.0f,	1.0f,	false,	IVec3(0),	tex2DTexelFetchFloat,		evalTexelFetch2D,		BOTH),
3398 		CASE_SPEC(isampler2d,					FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4( 63.9f,  63.9f,  0.0f,  0.0f),	false,	2.0f,	2.0f,	false,	IVec3(0),	tex2DTexelFetchInt,			evalTexelFetch2D,		BOTH),
3399 		CASE_SPEC(usampler2d,					FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4( 15.9f,  15.9f,  0.0f,  0.0f),	false,	4.0f,	4.0f,	false,	IVec3(0),	tex2DTexelFetchUint,		evalTexelFetch2D,		BOTH),
3400 
3401 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4(127.9f, 127.9f,  3.9f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex2DArrayTexelFetchFixed,	evalTexelFetch2DArray,	BOTH),
3402 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4( 63.9f,  63.9f,  3.9f,  0.0f),	false,	1.0f,	1.0f,	false,	IVec3(0),	tex2DArrayTexelFetchFloat,	evalTexelFetch2DArray,	BOTH),
3403 		CASE_SPEC(isampler2darray,				FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4( 31.9f,  31.9f,  3.9f,  0.0f),	false,	2.0f,	2.0f,	false,	IVec3(0),	tex2DArrayTexelFetchInt,	evalTexelFetch2DArray,	BOTH),
3404 		CASE_SPEC(usampler2darray,				FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4( 15.9f,  15.9f,  3.9f,  0.0f),	false,	3.0f,	3.0f,	false,	IVec3(0),	tex2DArrayTexelFetchUint,	evalTexelFetch2DArray,	BOTH),
3405 
3406 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4(63.9f,  31.9f,  31.9f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DTexelFetchFixed,		evalTexelFetch3D,		BOTH),
3407 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4(31.9f,  15.9f,  15.9f,  0.0f),	false,	1.0f,	1.0f,	false,	IVec3(0),	tex3DTexelFetchFloat,		evalTexelFetch3D,		BOTH),
3408 		CASE_SPEC(isampler3d,					FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4(15.9f,   7.9f,   7.9f,  0.0f),	false,	2.0f,	2.0f,	false,	IVec3(0),	tex3DTexelFetchInt,			evalTexelFetch3D,		BOTH),
3409 		CASE_SPEC(usampler3d,					FUNCTION_TEXELFETCH,	Vec4(0.0f, 0.0f, 0.0f, 0.0f),	Vec4(63.9f,  31.9f,  31.9f,  0.0f),	false,	0.0f,	0.0f,	false,	IVec3(0),	tex3DTexelFetchUint,		evalTexelFetch3D,		BOTH)
3410 	};
3411 	createCaseGroup(this, "texelfetch", "texelFetch() Tests", texelFetchCases, DE_LENGTH_OF_ARRAY(texelFetchCases));
3412 
3413 	// texelFetchOffset() cases
3414 	static const TexFuncCaseSpec texelFetchOffsetCases[] =
3415 	{
3416 		//		  Name							Function				MinCoord							MaxCoord						Bias?	MinLod	MaxLod	Offset?	Offset		Format						EvalFunc				Flags
3417 		CASE_SPEC(sampler2d_fixed,				FUNCTION_TEXELFETCH,	Vec4( 8.0f, -7.0f, 0.0f, 0.0f),	Vec4(263.9f, 248.9f,  0.0f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DTexelFetchFixed,		evalTexelFetch2D,		BOTH),
3418 		CASE_SPEC(sampler2d_float,				FUNCTION_TEXELFETCH,	Vec4(-7.0f,  8.0f, 0.0f, 0.0f),	Vec4(120.9f, 135.9f,  0.0f,  0.0f),	false,	1.0f,	1.0f,	true,	IVec3(7, -8, 0),	tex2DTexelFetchFloat,		evalTexelFetch2D,		BOTH),
3419 		CASE_SPEC(isampler2d,					FUNCTION_TEXELFETCH,	Vec4( 8.0f, -7.0f, 0.0f, 0.0f),	Vec4( 71.9f,  56.9f,  0.0f,  0.0f),	false,	2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DTexelFetchInt,			evalTexelFetch2D,		BOTH),
3420 		CASE_SPEC(usampler2d,					FUNCTION_TEXELFETCH,	Vec4(-7.0f,  8.0f, 0.0f, 0.0f),	Vec4(  8.9f,  23.9f,  0.0f,  0.0f),	false,	4.0f,	4.0f,	true,	IVec3(7, -8, 0),	tex2DTexelFetchUint,		evalTexelFetch2D,		BOTH),
3421 
3422 		CASE_SPEC(sampler2darray_fixed,			FUNCTION_TEXELFETCH,	Vec4( 8.0f, -7.0f, 0.0f, 0.0f),	Vec4(135.9f, 120.9f,  3.9f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayTexelFetchFixed,	evalTexelFetch2DArray,	BOTH),
3423 		CASE_SPEC(sampler2darray_float,			FUNCTION_TEXELFETCH,	Vec4(-7.0f,  8.0f, 0.0f, 0.0f),	Vec4( 56.9f,  71.9f,  3.9f,  0.0f),	false,	1.0f,	1.0f,	true,	IVec3(7, -8, 0),	tex2DArrayTexelFetchFloat,	evalTexelFetch2DArray,	BOTH),
3424 		CASE_SPEC(isampler2darray,				FUNCTION_TEXELFETCH,	Vec4( 8.0f, -7.0f, 0.0f, 0.0f),	Vec4( 39.9f,  24.9f,  3.9f,  0.0f),	false,	2.0f,	2.0f,	true,	IVec3(-8, 7, 0),	tex2DArrayTexelFetchInt,	evalTexelFetch2DArray,	BOTH),
3425 		CASE_SPEC(usampler2darray,				FUNCTION_TEXELFETCH,	Vec4(-7.0f,  8.0f, 0.0f, 0.0f),	Vec4(  8.9f,  23.9f,  3.9f,  0.0f),	false,	3.0f,	3.0f,	true,	IVec3(7, -8, 0),	tex2DArrayTexelFetchUint,	evalTexelFetch2DArray,	BOTH),
3426 
3427 		CASE_SPEC(sampler3d_fixed,				FUNCTION_TEXELFETCH,	Vec4( 8.0f, -7.0f, -3.0f, 0.0f),Vec4(71.9f,  24.9f,  28.9f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DTexelFetchFixed,		evalTexelFetch3D,		BOTH),
3428 		CASE_SPEC(sampler3d_float,				FUNCTION_TEXELFETCH,	Vec4(-7.0f, -3.0f,  8.0f, 0.0f),Vec4(24.9f,  12.9f,  23.9f,  0.0f),	false,	1.0f,	1.0f,	true,	IVec3(7, 3, -8),	tex3DTexelFetchFloat,		evalTexelFetch3D,		BOTH),
3429 		CASE_SPEC(isampler3d,					FUNCTION_TEXELFETCH,	Vec4(-3.0f,  8.0f, -7.0f, 0.0f),Vec4(12.9f,  15.9f,   0.9f,  0.0f),	false,	2.0f,	2.0f,	true,	IVec3(3, -8, 7),	tex3DTexelFetchInt,			evalTexelFetch3D,		BOTH),
3430 		CASE_SPEC(usampler3d,					FUNCTION_TEXELFETCH,	Vec4( 8.0f, -7.0f, -3.0f, 0.0f),Vec4(71.9f,  24.9f,  28.9f,  0.0f),	false,	0.0f,	0.0f,	true,	IVec3(-8, 7, 3),	tex3DTexelFetchUint,		evalTexelFetch3D,		BOTH)
3431 	};
3432 	createCaseGroup(this, "texelfetchoffset", "texelFetchOffset() Tests", texelFetchOffsetCases, DE_LENGTH_OF_ARRAY(texelFetchOffsetCases));
3433 
3434 	// texture query functions
3435 	{
3436 		struct TexQueryFuncCaseSpec
3437 		{
3438 			const char*		name;
3439 			const char*		samplerName;
3440 			TextureSpec		textureSpec;
3441 		};
3442 
3443 		de::MovePtr<tcu::TestCaseGroup>			queryGroup	(new tcu::TestCaseGroup(m_testCtx, "query", "Texture query function tests"));
3444 
3445 		// textureSize() cases
3446 		{
3447 			const TexQueryFuncCaseSpec textureSizeCases[] =
3448 			{
3449 				{ "sampler2d_fixed",			"sampler2D",				tex2DFixed			},
3450 				{ "sampler2d_float",			"sampler2D",				tex2DFloat			},
3451 				{ "isampler2d",					"isampler2D",				tex2DInt			},
3452 				{ "usampler2d",					"usampler2D",				tex2DUint			},
3453 				{ "sampler2dshadow",			"sampler2DShadow",			tex2DShadow			},
3454 				{ "sampler3d_fixed",			"sampler3D",				tex3DFixed			},
3455 				{ "sampler3d_float",			"sampler3D",				tex3DFloat			},
3456 				{ "isampler3d",					"isampler3D",				tex3DInt			},
3457 				{ "usampler3d",					"usampler3D",				tex3DUint			},
3458 				{ "samplercube_fixed",			"samplerCube",				texCubeFixed		},
3459 				{ "samplercube_float",			"samplerCube",				texCubeFloat		},
3460 				{ "isamplercube",				"isamplerCube",				texCubeInt			},
3461 				{ "usamplercube",				"usamplerCube",				texCubeUint			},
3462 				{ "samplercubeshadow",			"samplerCubeShadow",		texCubeShadow		},
3463 				{ "sampler2darray_fixed",		"sampler2DArray",			tex2DArrayFixed		},
3464 				{ "sampler2darray_float",		"sampler2DArray",			tex2DArrayFloat		},
3465 				{ "isampler2darray",			"isampler2DArray",			tex2DArrayInt		},
3466 				{ "usampler2darray",			"usampler2DArray",			tex2DArrayUint		},
3467 				{ "sampler2darrayshadow",		"sampler2DArrayShadow",		tex2DArrayShadow	},
3468 				{ "samplercubearray_fixed",		"samplerCubeArray",			texCubeArrayFixed	},
3469 				{ "samplercubearray_float",		"samplerCubeArray",			texCubeArrayFloat	},
3470 				{ "isamplercubearray",			"isamplerCubeArray",		texCubeArrayInt		},
3471 				{ "usamplercubearray",			"usamplerCubeArray",		texCubeArrayUint	},
3472 				{ "samplercubearrayshadow",		"samplerCubeArrayShadow",	texCubeArrayShadow	},
3473 				{ "sampler1d_fixed",			"sampler1D",				tex1DFixed			},
3474 				{ "sampler1d_float",			"sampler1D",				tex1DFloat			},
3475 				{ "isampler1d",					"isampler1D",				tex1DInt			},
3476 				{ "usampler1d",					"usampler1D",				tex1DUint			},
3477 				{ "sampler1dshadow",			"sampler1DShadow",			tex1DShadow			},
3478 				{ "sampler1darray_fixed",		"sampler1DArray",			tex1DArrayFixed		},
3479 				{ "sampler1darray_float",		"sampler1DArray",			tex1DArrayFloat		},
3480 				{ "isampler1darray",			"isampler1DArray",			tex1DArrayInt		},
3481 				{ "usampler1darray",			"usampler1DArray",			tex1DArrayUint		},
3482 				{ "sampler1darrayshadow",		"sampler1DArrayShadow",		tex1DArrayShadow	},
3483 			};
3484 
3485 			de::MovePtr<tcu::TestCaseGroup>		group		(new tcu::TestCaseGroup(m_testCtx, "texturesize", "textureSize() Tests"));
3486 
3487 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureSizeCases); ++ndx)
3488 			{
3489 				const TexQueryFuncCaseSpec&		caseSpec	= textureSizeCases[ndx];
3490 
3491 				group->addChild(new TextureQueryCase(m_testCtx, (std::string(caseSpec.name) + "_vertex"),   "", caseSpec.samplerName, caseSpec.textureSpec, true,  QUERYFUNCTION_TEXTURESIZE));
3492 				group->addChild(new TextureQueryCase(m_testCtx, (std::string(caseSpec.name) + "_fragment"), "", caseSpec.samplerName, caseSpec.textureSpec, false, QUERYFUNCTION_TEXTURESIZE));
3493 			}
3494 
3495 			queryGroup->addChild(group.release());
3496 		}
3497 
3498 		// textureSamples() cases
3499 		{
3500 			const TexQueryFuncCaseSpec textureSamplesCases[] =
3501 			{
3502 				{ "sampler2dms_fixed",			"sampler2DMS",				tex2DFixed			},
3503 				{ "sampler2dms_float",			"sampler2DMS",				tex2DFloat			},
3504 				{ "isampler2dms",				"isampler2DMS",				tex2DInt			},
3505 				{ "usampler2dms",				"usampler2DMS",				tex2DUint			},
3506 				{ "sampler2dmsarray_fixed",		"sampler2DMSArray",			tex2DArrayFixed		},
3507 				{ "sampler2dmsarray_float",		"sampler2DMSArray",			tex2DArrayFloat		},
3508 				{ "isampler2dmsarray",			"isampler2DMSArray",		tex2DArrayInt		},
3509 				{ "usampler2dmsarray",			"usampler2DMSArray",		tex2DArrayUint		},
3510 			};
3511 
3512 			de::MovePtr<tcu::TestCaseGroup>		group		(new tcu::TestCaseGroup(m_testCtx, "texturesamples", "textureSamples() Tests"));
3513 
3514 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureSamplesCases); ++ndx)
3515 			{
3516 				const TexQueryFuncCaseSpec&		caseSpec	= textureSamplesCases[ndx];
3517 
3518 				group->addChild(new TextureQueryCase(m_testCtx, (std::string(caseSpec.name) + "_vertex"),   "", caseSpec.samplerName, caseSpec.textureSpec, true,  QUERYFUNCTION_TEXTURESAMPLES));
3519 				group->addChild(new TextureQueryCase(m_testCtx, (std::string(caseSpec.name) + "_fragment"), "", caseSpec.samplerName, caseSpec.textureSpec, false, QUERYFUNCTION_TEXTURESAMPLES));
3520 			}
3521 
3522 			queryGroup->addChild(group.release());
3523 		}
3524 
3525 		// textureQueryLevels() cases
3526 		{
3527 			const TexQueryFuncCaseSpec textureQueryLevelsCases[] =
3528 			{
3529 				{ "sampler2d_fixed",			"sampler2D",				tex2DFixed			},
3530 				{ "sampler2d_float",			"sampler2D",				tex2DFloat			},
3531 				{ "isampler2d",					"isampler2D",				tex2DInt			},
3532 				{ "usampler2d",					"usampler2D",				tex2DUint			},
3533 				{ "sampler2dshadow",			"sampler2DShadow",			tex2DShadow			},
3534 				{ "sampler3d_fixed",			"sampler3D",				tex3DFixed			},
3535 				{ "sampler3d_float",			"sampler3D",				tex3DFloat			},
3536 				{ "isampler3d",					"isampler3D",				tex3DInt			},
3537 				{ "usampler3d",					"usampler3D",				tex3DUint			},
3538 				{ "samplercube_fixed",			"samplerCube",				texCubeFixed		},
3539 				{ "samplercube_float",			"samplerCube",				texCubeFloat		},
3540 				{ "isamplercube",				"isamplerCube",				texCubeInt			},
3541 				{ "usamplercube",				"usamplerCube",				texCubeUint			},
3542 				{ "samplercubeshadow",			"samplerCubeShadow",		texCubeShadow		},
3543 				{ "sampler2darray_fixed",		"sampler2DArray",			tex2DArrayFixed		},
3544 				{ "sampler2darray_float",		"sampler2DArray",			tex2DArrayFloat		},
3545 				{ "isampler2darray",			"isampler2DArray",			tex2DArrayInt		},
3546 				{ "usampler2darray",			"usampler2DArray",			tex2DArrayUint		},
3547 				{ "sampler2darrayshadow",		"sampler2DArrayShadow",		tex2DArrayShadow	},
3548 				{ "samplercubearray_fixed",		"samplerCubeArray",			texCubeArrayFixed	},
3549 				{ "samplercubearray_float",		"samplerCubeArray",			texCubeArrayFloat	},
3550 				{ "isamplercubearray",			"isamplerCubeArray",		texCubeArrayInt		},
3551 				{ "usamplercubearray",			"usamplerCubeArray",		texCubeArrayUint	},
3552 				{ "samplercubearrayshadow",		"samplerCubeArrayShadow",	texCubeArrayShadow	},
3553 				{ "sampler1d_fixed",			"sampler1D",				tex1DFixed			},
3554 				{ "sampler1d_float",			"sampler1D",				tex1DFloat			},
3555 				{ "isampler1d",					"isampler1D",				tex1DInt			},
3556 				{ "usampler1d",					"usampler1D",				tex1DUint			},
3557 				{ "sampler1dshadow",			"sampler1DShadow",			tex1DShadow			},
3558 				{ "sampler1darray_fixed",		"sampler1DArray",			tex1DArrayFixed		},
3559 				{ "sampler1darray_float",		"sampler1DArray",			tex1DArrayFloat		},
3560 				{ "isampler1darray",			"isampler1DArray",			tex1DArrayInt		},
3561 				{ "usampler1darray",			"usampler1DArray",			tex1DArrayUint		},
3562 				{ "sampler1darrayshadow",		"sampler1DArrayShadow",		tex1DArrayShadow	},
3563 			};
3564 
3565 			de::MovePtr<tcu::TestCaseGroup>		group		(new tcu::TestCaseGroup(m_testCtx, "texturequerylevels", "textureQueryLevels() Tests"));
3566 
3567 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureQueryLevelsCases); ++ndx)
3568 			{
3569 				const TexQueryFuncCaseSpec&		caseSpec	= textureQueryLevelsCases[ndx];
3570 
3571 				group->addChild(new TextureQueryCase(m_testCtx, (std::string(caseSpec.name) + "_vertex"),   "", caseSpec.samplerName, caseSpec.textureSpec, true,  QUERYFUNCTION_TEXTUREQUERYLEVELS));
3572 				group->addChild(new TextureQueryCase(m_testCtx, (std::string(caseSpec.name) + "_fragment"), "", caseSpec.samplerName, caseSpec.textureSpec, false, QUERYFUNCTION_TEXTUREQUERYLEVELS));
3573 			}
3574 
3575 			queryGroup->addChild(group.release());
3576 		}
3577 
3578 		// textureQueryLod() cases
3579 		{
3580 			const TexQueryFuncCaseSpec textureQueryLodCases[] =
3581 			{
3582 				{ "sampler2d_fixed",			"sampler2D",				tex2DMipmapFixed			},
3583 				{ "sampler2d_float",			"sampler2D",				tex2DMipmapFloat			},
3584 				{ "isampler2d",					"isampler2D",				tex2DMipmapInt				},
3585 				{ "usampler2d",					"usampler2D",				tex2DMipmapUint				},
3586 				{ "sampler2dshadow",			"sampler2DShadow",			tex2DMipmapShadow			},
3587 				{ "sampler3d_fixed",			"sampler3D",				tex3DMipmapFixed			},
3588 				{ "sampler3d_float",			"sampler3D",				tex3DMipmapFloat			},
3589 				{ "isampler3d",					"isampler3D",				tex3DMipmapInt				},
3590 				{ "usampler3d",					"usampler3D",				tex3DMipmapUint				},
3591 				{ "samplercube_fixed",			"samplerCube",				texCubeMipmapFixed			},
3592 				{ "samplercube_float",			"samplerCube",				texCubeMipmapFloat			},
3593 				{ "isamplercube",				"isamplerCube",				texCubeMipmapInt			},
3594 				{ "usamplercube",				"usamplerCube",				texCubeMipmapUint			},
3595 				{ "samplercubeshadow",			"samplerCubeShadow",		texCubeMipmapShadow			},
3596 				{ "sampler2darray_fixed",		"sampler2DArray",			tex2DArrayMipmapFixed		},
3597 				{ "sampler2darray_float",		"sampler2DArray",			tex2DArrayMipmapFloat		},
3598 				{ "isampler2darray",			"isampler2DArray",			tex2DArrayMipmapInt			},
3599 				{ "usampler2darray",			"usampler2DArray",			tex2DArrayMipmapUint		},
3600 				{ "sampler2darrayshadow",		"sampler2DArrayShadow",		tex2DArrayMipmapShadow		},
3601 				{ "samplercubearray_fixed",		"samplerCubeArray",			texCubeArrayMipmapFixed		},
3602 				{ "samplercubearray_float",		"samplerCubeArray",			texCubeArrayMipmapFloat		},
3603 				{ "isamplercubearray",			"isamplerCubeArray",		texCubeArrayMipmapInt		},
3604 				{ "usamplercubearray",			"usamplerCubeArray",		texCubeArrayMipmapUint		},
3605 				{ "samplercubearrayshadow",		"samplerCubeArrayShadow",	texCubeArrayMipmapShadow	},
3606 				{ "sampler1d_fixed",			"sampler1D",				tex1DMipmapFixed			},
3607 				{ "sampler1d_float",			"sampler1D",				tex1DMipmapFloat			},
3608 				{ "isampler1d",					"isampler1D",				tex1DMipmapInt				},
3609 				{ "usampler1d",					"usampler1D",				tex1DMipmapUint				},
3610 				{ "sampler1dshadow",			"sampler1DShadow",			tex1DMipmapShadow			},
3611 				{ "sampler1darray_fixed",		"sampler1DArray",			tex1DArrayMipmapFixed		},
3612 				{ "sampler1darray_float",		"sampler1DArray",			tex1DArrayMipmapFloat		},
3613 				{ "isampler1darray",			"isampler1DArray",			tex1DArrayMipmapInt			},
3614 				{ "usampler1darray",			"usampler1DArray",			tex1DArrayMipmapUint		},
3615 				{ "sampler1darrayshadow",		"sampler1DArrayShadow",		tex1DArrayMipmapShadow		},
3616 			};
3617 
3618 			de::MovePtr<tcu::TestCaseGroup>		group		(new tcu::TestCaseGroup(m_testCtx, "texturequerylod", "textureQueryLod() Tests"));
3619 
3620 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureQueryLodCases); ++ndx)
3621 			{
3622 				const TexQueryFuncCaseSpec&		caseSpec	= textureQueryLodCases[ndx];
3623 
3624 				// available only in fragment shader
3625 				group->addChild(new TextureQueryCase(m_testCtx, (std::string(caseSpec.name) + "_fragment"), "", caseSpec.samplerName, caseSpec.textureSpec, false, QUERYFUNCTION_TEXTUREQUERYLOD));
3626 			}
3627 
3628 			queryGroup->addChild(group.release());
3629 		}
3630 
3631 		addChild(queryGroup.release());
3632 	}
3633 }
3634 
3635 } // anonymous
3636 
createTextureFunctionTests(tcu::TestContext & testCtx)3637 tcu::TestCaseGroup* createTextureFunctionTests (tcu::TestContext& testCtx)
3638 {
3639 	return new ShaderTextureFunctionTests(testCtx);
3640 }
3641 
3642 } // sr
3643 } // vkt
3644