1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Texture access function tests.
22 *//*--------------------------------------------------------------------*/
24 #include "es2fShaderTextureFunctionTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "glsShaderLibrary.hpp"
27 #include "glsTextureTestUtil.hpp"
28 #include "gluTexture.hpp"
29 #include "gluTextureUtil.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuMatrix.hpp"
32 #include "tcuMatrixUtil.hpp"
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
51 FUNCTION_TEXTURE = 0, //!< texture(), textureOffset()
52 FUNCTION_TEXTUREPROJ, //!< textureProj(), textureProjOffset()
53 FUNCTION_TEXTUREPROJ3, //!< textureProj(sampler2D, vec3)
54 FUNCTION_TEXTURELOD, // ...
55 FUNCTION_TEXTUREPROJLOD,
56 FUNCTION_TEXTUREPROJLOD3, //!< textureProjLod(sampler2D, vec3)
61 inline bool functionHasProj (Function function)
63 return function == FUNCTION_TEXTUREPROJ ||
64 function == FUNCTION_TEXTUREPROJ3 ||
65 function == FUNCTION_TEXTUREPROJLOD ||
66 function == FUNCTION_TEXTUREPROJLOD3;
69 inline bool functionHasLod (Function function)
71 return function == FUNCTION_TEXTURELOD ||
72 function == FUNCTION_TEXTUREPROJLOD ||
73 function == FUNCTION_TEXTUREPROJLOD3;
76 struct TextureLookupSpec
86 // Bias or Lod for *Lod* functions
90 TextureLookupSpec (void)
91 : function (FUNCTION_LAST)
100 TextureLookupSpec (Function function_,
101 const tcu::Vec4& minCoord_,
102 const tcu::Vec4& maxCoord_,
106 : function (function_)
107 , minCoord (minCoord_)
108 , maxCoord (maxCoord_)
110 , minLodBias (minLodBias_)
111 , maxLodBias (maxLodBias_)
119 TEXTURETYPE_CUBE_MAP,
126 TextureType type; //!< Texture type (2D, cubemap, ...)
132 tcu::Sampler sampler;
135 : type (TEXTURETYPE_LAST)
144 TextureSpec (TextureType type_,
150 const tcu::Sampler& sampler_)
153 , dataType (dataType_)
156 , numLevels (numLevels_)
162 struct TexLookupParams
168 TexLookupParams (void)
185 typedef void (*TexEvalFunc) (gls::ShaderEvalContext& c, const TexLookupParams& lookupParams);
187 inline Vec4 texture2D (const gls::ShaderEvalContext& c, float s, float t, float lod) { return c.textures[0].tex2D->sample(c.textures[0].sampler, s, t, lod); }
188 inline Vec4 textureCube (const gls::ShaderEvalContext& c, float s, float t, float r, float lod) { return c.textures[0].texCube->sample(c.textures[0].sampler, s, t, r, lod); }
191 static void evalTexture2D (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod)*p.scale + p.bias; }
192 static void evalTextureCube (gls::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; }
194 static void evalTexture2DBias (gls::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; }
195 static void evalTextureCubeBias (gls::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; }
197 static void evalTexture2DProj3 (gls::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; }
198 static void evalTexture2DProj3Bias (gls::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; }
199 static void evalTexture2DProj (gls::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; }
200 static void evalTexture2DProjBias (gls::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; }
202 static void evalTexture2DLod (gls::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; }
203 static void evalTextureCubeLod (gls::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; }
205 static void evalTexture2DProjLod3 (gls::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; }
206 static void evalTexture2DProjLod (gls::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; }
208 class TexLookupEvaluator : public gls::ShaderEvaluator
211 TexLookupEvaluator (TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {}
213 virtual void evaluate (gls::ShaderEvalContext& ctx) { m_evalFunc(ctx, m_lookupParams); }
216 TexEvalFunc m_evalFunc;
217 const TexLookupParams& m_lookupParams;
220 class ShaderTextureFunctionCase : public gls::ShaderRenderCase
223 ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase);
224 ~ShaderTextureFunctionCase (void);
230 void setupUniforms (int programID, const tcu::Vec4& constCoords);
233 void initTexture (void);
234 void initShaderSources (void);
236 TextureLookupSpec m_lookupSpec;
237 TextureSpec m_textureSpec;
239 TexLookupParams m_lookupParams;
240 TexLookupEvaluator m_evaluator;
242 glu::Texture2D* m_texture2D;
243 glu::TextureCube* m_textureCube;
246 ShaderTextureFunctionCase::ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase)
247 : gls::ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator)
248 , m_lookupSpec (lookup)
249 , m_textureSpec (texture)
250 , m_evaluator (evalFunc, m_lookupParams)
251 , m_texture2D (DE_NULL)
252 , m_textureCube (DE_NULL)
256 ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void)
259 delete m_textureCube;
262 void ShaderTextureFunctionCase::init (void)
266 const glw::Functions& gl = m_renderCtx.getFunctions();
267 int numVertexUnits = 0;
268 gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexUnits);
269 if (numVertexUnits < 1)
270 throw tcu::NotSupportedError("Vertex shader texture access is not supported");
274 // Base coord scale & bias
275 Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord;
276 Vec4 b = m_lookupSpec.minCoord;
278 float baseCoordTrans[] =
280 s.x(), 0.0f, 0.f, b.x(),
281 0.f, s.y(), 0.f, b.y(),
282 s.z()/2.f, -s.z()/2.f, 0.f, s.z()/2.f + b.z(),
283 -s.w()/2.f, s.w()/2.f, 0.f, s.w()/2.f + b.w()
286 m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans));
289 if (functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias)
291 float s = m_lookupSpec.maxLodBias-m_lookupSpec.minLodBias;
292 float b = m_lookupSpec.minLodBias;
293 float lodCoordTrans[] =
295 s/2.0f, s/2.0f, 0.f, b,
296 0.0f, 0.0f, 0.0f, 0.0f,
297 0.0f, 0.0f, 0.0f, 0.0f,
298 0.0f, 0.0f, 0.0f, 0.0f
301 m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans));
307 gls::ShaderRenderCase::init();
310 void ShaderTextureFunctionCase::initTexture (void)
312 static const IVec4 texCubeSwz[] =
321 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST);
323 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
324 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
325 tcu::IVec2 viewportSize = getViewportSize();
326 bool isProj = functionHasProj(m_lookupSpec.function);
327 float proj = isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f;
329 switch (m_textureSpec.type)
333 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
334 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
335 Vec4 cBias = fmtInfo.valueMin;
336 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4);
338 m_texture2D = new glu::Texture2D(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width, m_textureSpec.height);
339 for (int level = 0; level < m_textureSpec.numLevels; level++)
341 float fA = float(level)*cStep;
343 Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB);
344 Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA);
346 m_texture2D->getRefTexture().allocLevel(level);
347 tcu::fillWithGrid(m_texture2D->getRefTexture().getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB);
349 m_texture2D->upload();
352 float dudx = (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width / (float)viewportSize[0];
353 float dvdy = (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height / (float)viewportSize[1];
354 m_lookupParams.lod = glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
356 // Append to texture list.
357 m_textures.push_back(gls::TextureBinding(m_texture2D, m_textureSpec.sampler));
361 case TEXTURETYPE_CUBE_MAP:
363 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
364 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
365 Vec4 cBias = fmtInfo.valueMin;
366 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4);
368 DE_ASSERT(m_textureSpec.width == m_textureSpec.height);
369 m_textureCube = new glu::TextureCube(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width);
370 for (int level = 0; level < m_textureSpec.numLevels; level++)
372 float fA = float(level)*cStep;
376 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
378 const IVec4& swzA = texCubeSwz[face];
380 Vec4 colorA = cBias + cScale*f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]);
381 Vec4 colorB = cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]);
383 m_textureCube->getRefTexture().allocLevel((tcu::CubeFace)face, level);
384 tcu::fillWithGrid(m_textureCube->getRefTexture().getLevelFace(level, (tcu::CubeFace)face), de::max(1, baseCellSize>>level), colorA, colorB);
387 m_textureCube->upload();
389 // Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
390 DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005);
391 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]));
392 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]));
394 tcu::CubeFaceFloatCoords c00 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
395 tcu::CubeFaceFloatCoords c10 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.maxCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
396 tcu::CubeFaceFloatCoords c01 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.maxCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
397 float dudx = (c10.s - c00.s)*(float)m_textureSpec.width / (float)viewportSize[0];
398 float dvdy = (c01.t - c00.t)*(float)m_textureSpec.height / (float)viewportSize[1];
400 m_lookupParams.lod = glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
402 m_textures.push_back(gls::TextureBinding(m_textureCube, m_textureSpec.sampler));
410 // Set lookup scale & bias
411 m_lookupParams.scale = fmtInfo.lookupScale;
412 m_lookupParams.bias = fmtInfo.lookupBias;
415 void ShaderTextureFunctionCase::initShaderSources (void)
417 Function function = m_lookupSpec.function;
418 bool isVtxCase = m_isVertexCase;
419 bool isProj = functionHasProj(function);
420 bool is2DProj4 = m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD);
421 bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias;
422 int texCoordComps = m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3;
423 int extraCoordComps = isProj ? (is2DProj4 ? 2 : 1) : 0;
424 glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps+extraCoordComps);
425 glu::Precision coordPrec = glu::PRECISION_MEDIUMP;
426 const char* coordTypeName = glu::getDataTypeName(coordType);
427 const char* coordPrecName = glu::getPrecisionName(coordPrec);
428 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
429 glu::DataType samplerType = glu::TYPE_LAST;
430 const char* baseFuncName = m_textureSpec.type == TEXTURETYPE_2D ? "texture2D" : "textureCube";
431 const char* funcExt = DE_NULL;
433 switch (m_textureSpec.type)
435 case TEXTURETYPE_2D: samplerType = glu::getSampler2DType(texFmt); break;
436 case TEXTURETYPE_CUBE_MAP: samplerType = glu::getSamplerCubeType(texFmt); break;
441 switch (m_lookupSpec.function)
443 case FUNCTION_TEXTURE: funcExt = ""; break;
444 case FUNCTION_TEXTUREPROJ: funcExt = "Proj"; break;
445 case FUNCTION_TEXTUREPROJ3: funcExt = "Proj"; break;
446 case FUNCTION_TEXTURELOD: funcExt = "Lod"; break;
447 case FUNCTION_TEXTUREPROJLOD: funcExt = "ProjLod"; break;
448 case FUNCTION_TEXTUREPROJLOD3: funcExt = "ProjLod"; break;
453 std::ostringstream vert;
454 std::ostringstream frag;
455 std::ostringstream& op = isVtxCase ? vert : frag;
457 vert << "attribute highp vec4 a_position;\n"
458 << "attribute " << coordPrecName << " " << coordTypeName << " a_in0;\n";
461 vert << "attribute " << coordPrecName << " float a_in1;\n";
465 vert << "varying mediump vec4 v_color;\n";
466 frag << "varying mediump vec4 v_color;\n";
470 vert << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
471 frag << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
475 vert << "varying " << coordPrecName << " float v_lodBias;\n";
476 frag << "varying " << coordPrecName << " float v_lodBias;\n";
481 op << "uniform lowp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";
483 vert << "\nvoid main()\n{\n"
484 << "\tgl_Position = a_position;\n";
485 frag << "\nvoid main()\n{\n";
488 vert << "\tv_color = ";
490 frag << "\tgl_FragColor = ";
494 const char* texCoord = isVtxCase ? "a_in0" : "v_texCoord";
495 const char* lodBias = isVtxCase ? "a_in1" : "v_lodBias";
497 op << baseFuncName << funcExt;
498 op << "(u_sampler, " << texCoord;
500 if (functionHasLod(function) || m_lookupSpec.useBias)
501 op << ", " << lodBias;
507 frag << "\tgl_FragColor = v_color;\n";
510 vert << "\tv_texCoord = a_in0;\n";
513 vert << "\tv_lodBias = a_in1;\n";
519 m_vertShaderSource = vert.str();
520 m_fragShaderSource = frag.str();
523 void ShaderTextureFunctionCase::deinit (void)
525 gls::ShaderRenderCase::deinit();
528 delete m_textureCube;
530 m_texture2D = DE_NULL;
531 m_textureCube = DE_NULL;
534 void ShaderTextureFunctionCase::setupUniforms (int programID, const tcu::Vec4&)
536 const glw::Functions& gl = m_renderCtx.getFunctions();
537 gl.uniform1i(gl.getUniformLocation(programID, "u_sampler"), 0);
540 ShaderTextureFunctionTests::ShaderTextureFunctionTests (Context& context)
541 : TestCaseGroup(context, "texture_functions", "Texture Access Function Tests")
545 ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void)
549 struct TexFuncCaseSpec
552 TextureLookupSpec lookupSpec;
554 TexEvalFunc evalFunc;
557 #define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, TEXSPEC, EVALFUNC) \
558 { #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD), TEXSPEC, EVALFUNC }
560 static void createCaseGroup (TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases, bool isVertex)
562 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc);
563 parent->addChild(group);
565 for (int ndx = 0; ndx < numCases; ndx++)
566 group->addChild(new ShaderTextureFunctionCase(parent->getContext(), cases[ndx].name, "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, isVertex));
569 void ShaderTextureFunctionTests::init (void)
571 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
574 static const tcu::Sampler samplerLinearNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
575 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
576 static tcu::Sampler samplerLinearMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
577 tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR);
579 // GL_MAJOR_VERSION query does not exist on GLES2
580 // so succeeding query implies GLES3+ hardware.
581 glw::GLint majorVersion = 0;
582 gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
583 samplerLinearMipmap.seamlessCubeMap = (gl.getError() == GL_NO_ERROR);
586 // Type Format DataType W H L Sampler
587 static const TextureSpec tex2D (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap);
588 static const TextureSpec tex2DMipmap (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap);
590 static const TextureSpec texCube (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap);
591 static const TextureSpec texCubeMipmap (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap);
594 static const TexFuncCaseSpec vertexCases[] =
596 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
597 CASE_SPEC(texture2d, 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, tex2D, evalTexture2D),
598 // CASE_SPEC(texture2d_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, tex2D, evalTexture2DBias),
599 CASE_SPEC(texture2dproj_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, tex2D, evalTexture2DProj3),
600 CASE_SPEC(texture2dproj_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, tex2D, evalTexture2DProj),
601 CASE_SPEC(texture2dlod, 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, tex2DMipmap, evalTexture2DLod),
602 // CASE_SPEC(texture2dproj_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, tex2D, evalTexture2DProj3Bias),
603 // CASE_SPEC(texture2dproj_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, tex2D, evalTexture2DProjBias),
604 CASE_SPEC(texture2dprojlod_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, tex2D, evalTexture2DProjLod3),
605 CASE_SPEC(texture2dprojlod_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, tex2D, evalTexture2DProjLod),
606 CASE_SPEC(texturecube, 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, texCube, evalTextureCube),
607 // CASE_SPEC(texturecube_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, texCube, evalTextureCubeBias),
608 CASE_SPEC(texturecubelod, 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, texCubeMipmap, evalTextureCubeLod),
610 createCaseGroup(this, "vertex", "Vertex Shader Texture Lookups", &vertexCases[0], DE_LENGTH_OF_ARRAY(vertexCases), true);
613 static const TexFuncCaseSpec fragmentCases[] =
615 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
616 CASE_SPEC(texture2d, 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, tex2DMipmap, evalTexture2D),
617 CASE_SPEC(texture2d_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, tex2DMipmap, evalTexture2DBias),
618 CASE_SPEC(texture2dproj_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, tex2DMipmap, evalTexture2DProj3),
619 CASE_SPEC(texture2dproj_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, tex2DMipmap, evalTexture2DProj),
620 CASE_SPEC(texture2dproj_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, tex2DMipmap, evalTexture2DProj3Bias),
621 CASE_SPEC(texture2dproj_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, tex2DMipmap, evalTexture2DProjBias),
622 CASE_SPEC(texturecube, 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, texCubeMipmap, evalTextureCube),
623 CASE_SPEC(texturecube_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, texCubeMipmap, evalTextureCubeBias)
625 createCaseGroup(this, "fragment", "Fragment Shader Texture Lookups", &fragmentCases[0], DE_LENGTH_OF_ARRAY(fragmentCases), false);
629 gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
630 std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/invalid_texture_functions.test");
632 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, "invalid", "Invalid texture function usage", negativeCases);