/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 2.0 Module * ------------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Texture access function tests. *//*--------------------------------------------------------------------*/ #include "es2fShaderTextureFunctionTests.hpp" #include "glsShaderRenderCase.hpp" #include "glsShaderLibrary.hpp" #include "glsTextureTestUtil.hpp" #include "gluTexture.hpp" #include "gluTextureUtil.hpp" #include "tcuTextureUtil.hpp" #include "tcuMatrix.hpp" #include "tcuMatrixUtil.hpp" #include <sstream> #include "glwEnums.hpp" #include "glwFunctions.hpp" namespace deqp { namespace gles2 { namespace Functional { namespace { enum Function { FUNCTION_TEXTURE = 0, //!< texture(), textureOffset() FUNCTION_TEXTUREPROJ, //!< textureProj(), textureProjOffset() FUNCTION_TEXTUREPROJ3, //!< textureProj(sampler2D, vec3) FUNCTION_TEXTURELOD, // ... FUNCTION_TEXTUREPROJLOD, FUNCTION_TEXTUREPROJLOD3, //!< textureProjLod(sampler2D, vec3) FUNCTION_LAST }; inline bool functionHasProj (Function function) { return function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJ3 || function == FUNCTION_TEXTUREPROJLOD || function == FUNCTION_TEXTUREPROJLOD3; } inline bool functionHasLod (Function function) { return function == FUNCTION_TEXTURELOD || function == FUNCTION_TEXTUREPROJLOD || function == FUNCTION_TEXTUREPROJLOD3; } struct TextureLookupSpec { Function function; tcu::Vec4 minCoord; tcu::Vec4 maxCoord; // Bias bool useBias; // Bias or Lod for *Lod* functions float minLodBias; float maxLodBias; TextureLookupSpec (void) : function (FUNCTION_LAST) , minCoord (0.0f) , maxCoord (1.0f) , useBias (false) , minLodBias (0.0f) , maxLodBias (0.0f) { } TextureLookupSpec (Function function_, const tcu::Vec4& minCoord_, const tcu::Vec4& maxCoord_, bool useBias_, float minLodBias_, float maxLodBias_) : function (function_) , minCoord (minCoord_) , maxCoord (maxCoord_) , useBias (useBias_) , minLodBias (minLodBias_) , maxLodBias (maxLodBias_) { } }; enum TextureType { TEXTURETYPE_2D, TEXTURETYPE_CUBE_MAP, TEXTURETYPE_LAST }; struct TextureSpec { TextureType type; //!< Texture type (2D, cubemap, ...) deUint32 format; deUint32 dataType; int width; int height; int numLevels; tcu::Sampler sampler; TextureSpec (void) : type (TEXTURETYPE_LAST) , format (GL_NONE) , dataType (GL_NONE) , width (0) , height (0) , numLevels (0) { } TextureSpec (TextureType type_, deUint32 format_, deUint32 dataType_, int width_, int height_, int numLevels_, const tcu::Sampler& sampler_) : type (type_) , format (format_) , dataType (dataType_) , width (width_) , height (height_) , numLevels (numLevels_) , sampler (sampler_) { } }; struct TexLookupParams { float lod; tcu::Vec4 scale; tcu::Vec4 bias; TexLookupParams (void) : lod (0.0f) , scale (1.0f) , bias (0.0f) { } }; } // anonymous using tcu::Vec2; using tcu::Vec3; using tcu::Vec4; using tcu::IVec2; using tcu::IVec3; using tcu::IVec4; typedef void (*TexEvalFunc) (gls::ShaderEvalContext& c, const TexLookupParams& lookupParams); 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); } 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); } // Eval functions. 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; } 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; } 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; } 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; } 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; } 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; } 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; } 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; } 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; } 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; } 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; } 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; } class TexLookupEvaluator : public gls::ShaderEvaluator { public: TexLookupEvaluator (TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {} virtual void evaluate (gls::ShaderEvalContext& ctx) { m_evalFunc(ctx, m_lookupParams); } private: TexEvalFunc m_evalFunc; const TexLookupParams& m_lookupParams; }; class ShaderTextureFunctionCase : public gls::ShaderRenderCase { public: ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase); ~ShaderTextureFunctionCase (void); void init (void); void deinit (void); protected: void setupUniforms (int programID, const tcu::Vec4& constCoords); private: void initTexture (void); void initShaderSources (void); TextureLookupSpec m_lookupSpec; TextureSpec m_textureSpec; TexLookupParams m_lookupParams; TexLookupEvaluator m_evaluator; glu::Texture2D* m_texture2D; glu::TextureCube* m_textureCube; }; ShaderTextureFunctionCase::ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase) : gls::ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator) , m_lookupSpec (lookup) , m_textureSpec (texture) , m_evaluator (evalFunc, m_lookupParams) , m_texture2D (DE_NULL) , m_textureCube (DE_NULL) { } ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void) { delete m_texture2D; delete m_textureCube; } void ShaderTextureFunctionCase::init (void) { if (m_isVertexCase) { const glw::Functions& gl = m_renderCtx.getFunctions(); int numVertexUnits = 0; gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexUnits); if (numVertexUnits < 1) throw tcu::NotSupportedError("Vertex shader texture access is not supported"); } { // Base coord scale & bias Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord; Vec4 b = m_lookupSpec.minCoord; float baseCoordTrans[] = { s.x(), 0.0f, 0.f, b.x(), 0.f, s.y(), 0.f, b.y(), s.z()/2.f, -s.z()/2.f, 0.f, s.z()/2.f + b.z(), -s.w()/2.f, s.w()/2.f, 0.f, s.w()/2.f + b.w() }; m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans)); } if (functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias) { float s = m_lookupSpec.maxLodBias-m_lookupSpec.minLodBias; float b = m_lookupSpec.minLodBias; float lodCoordTrans[] = { s/2.0f, s/2.0f, 0.f, b, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans)); } initShaderSources(); initTexture(); gls::ShaderRenderCase::init(); } void ShaderTextureFunctionCase::initTexture (void) { static const IVec4 texCubeSwz[] = { IVec4(0,0,1,1), IVec4(1,1,0,0), IVec4(0,1,0,1), IVec4(1,0,1,0), IVec4(0,1,1,0), IVec4(1,0,0,1) }; DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST); tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType); tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); tcu::IVec2 viewportSize = getViewportSize(); bool isProj = functionHasProj(m_lookupSpec.function); float proj = isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f; switch (m_textureSpec.type) { case TEXTURETYPE_2D: { float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; Vec4 cBias = fmtInfo.valueMin; int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); m_texture2D = new glu::Texture2D(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width, m_textureSpec.height); for (int level = 0; level < m_textureSpec.numLevels; level++) { float fA = float(level)*cStep; float fB = 1.0f-fA; Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB); Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA); m_texture2D->getRefTexture().allocLevel(level); tcu::fillWithGrid(m_texture2D->getRefTexture().getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB); } m_texture2D->upload(); // Compute LOD. float dudx = (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width / (float)viewportSize[0]; float dvdy = (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height / (float)viewportSize[1]; m_lookupParams.lod = glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy); // Append to texture list. m_textures.push_back(gls::TextureBinding(m_texture2D, m_textureSpec.sampler)); break; } case TEXTURETYPE_CUBE_MAP: { float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; Vec4 cBias = fmtInfo.valueMin; int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); DE_ASSERT(m_textureSpec.width == m_textureSpec.height); m_textureCube = new glu::TextureCube(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width); for (int level = 0; level < m_textureSpec.numLevels; level++) { float fA = float(level)*cStep; float fB = 1.0f-fA; Vec2 f (fA, fB); for (int face = 0; face < tcu::CUBEFACE_LAST; face++) { const IVec4& swzA = texCubeSwz[face]; IVec4 swzB = 1-swzA; Vec4 colorA = cBias + cScale*f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]); Vec4 colorB = cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]); m_textureCube->getRefTexture().allocLevel((tcu::CubeFace)face, level); tcu::fillWithGrid(m_textureCube->getRefTexture().getLevelFace(level, (tcu::CubeFace)face), de::max(1, baseCellSize>>level), colorA, colorB); } } m_textureCube->upload(); // Compute LOD \note Assumes that only single side is accessed and R is constant major axis. DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005); 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])); 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])); tcu::CubeFaceFloatCoords c00 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); tcu::CubeFaceFloatCoords c10 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.maxCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); tcu::CubeFaceFloatCoords c01 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.maxCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); float dudx = (c10.s - c00.s)*(float)m_textureSpec.width / (float)viewportSize[0]; float dvdy = (c01.t - c00.t)*(float)m_textureSpec.height / (float)viewportSize[1]; m_lookupParams.lod = glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy); m_textures.push_back(gls::TextureBinding(m_textureCube, m_textureSpec.sampler)); break; } default: DE_ASSERT(DE_FALSE); } // Set lookup scale & bias m_lookupParams.scale = fmtInfo.lookupScale; m_lookupParams.bias = fmtInfo.lookupBias; } void ShaderTextureFunctionCase::initShaderSources (void) { Function function = m_lookupSpec.function; bool isVtxCase = m_isVertexCase; bool isProj = functionHasProj(function); bool is2DProj4 = m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD); bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias; int texCoordComps = m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3; int extraCoordComps = isProj ? (is2DProj4 ? 2 : 1) : 0; glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps+extraCoordComps); glu::Precision coordPrec = glu::PRECISION_MEDIUMP; const char* coordTypeName = glu::getDataTypeName(coordType); const char* coordPrecName = glu::getPrecisionName(coordPrec); tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType); glu::DataType samplerType = glu::TYPE_LAST; const char* baseFuncName = m_textureSpec.type == TEXTURETYPE_2D ? "texture2D" : "textureCube"; const char* funcExt = DE_NULL; switch (m_textureSpec.type) { case TEXTURETYPE_2D: samplerType = glu::getSampler2DType(texFmt); break; case TEXTURETYPE_CUBE_MAP: samplerType = glu::getSamplerCubeType(texFmt); break; default: DE_ASSERT(DE_FALSE); } switch (m_lookupSpec.function) { case FUNCTION_TEXTURE: funcExt = ""; break; case FUNCTION_TEXTUREPROJ: funcExt = "Proj"; break; case FUNCTION_TEXTUREPROJ3: funcExt = "Proj"; break; case FUNCTION_TEXTURELOD: funcExt = "Lod"; break; case FUNCTION_TEXTUREPROJLOD: funcExt = "ProjLod"; break; case FUNCTION_TEXTUREPROJLOD3: funcExt = "ProjLod"; break; default: DE_ASSERT(DE_FALSE); } std::ostringstream vert; std::ostringstream frag; std::ostringstream& op = isVtxCase ? vert : frag; vert << "attribute highp vec4 a_position;\n" << "attribute " << coordPrecName << " " << coordTypeName << " a_in0;\n"; if (hasLodBias) vert << "attribute " << coordPrecName << " float a_in1;\n"; if (isVtxCase) { vert << "varying mediump vec4 v_color;\n"; frag << "varying mediump vec4 v_color;\n"; } else { vert << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; frag << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; if (hasLodBias) { vert << "varying " << coordPrecName << " float v_lodBias;\n"; frag << "varying " << coordPrecName << " float v_lodBias;\n"; } } // Uniforms op << "uniform lowp " << glu::getDataTypeName(samplerType) << " u_sampler;\n"; vert << "\nvoid main()\n{\n" << "\tgl_Position = a_position;\n"; frag << "\nvoid main()\n{\n"; if (isVtxCase) vert << "\tv_color = "; else frag << "\tgl_FragColor = "; // Op. { const char* texCoord = isVtxCase ? "a_in0" : "v_texCoord"; const char* lodBias = isVtxCase ? "a_in1" : "v_lodBias"; op << baseFuncName << funcExt; op << "(u_sampler, " << texCoord; if (functionHasLod(function) || m_lookupSpec.useBias) op << ", " << lodBias; op << ");\n"; } if (isVtxCase) frag << "\tgl_FragColor = v_color;\n"; else { vert << "\tv_texCoord = a_in0;\n"; if (hasLodBias) vert << "\tv_lodBias = a_in1;\n"; } vert << "}\n"; frag << "}\n"; m_vertShaderSource = vert.str(); m_fragShaderSource = frag.str(); } void ShaderTextureFunctionCase::deinit (void) { gls::ShaderRenderCase::deinit(); delete m_texture2D; delete m_textureCube; m_texture2D = DE_NULL; m_textureCube = DE_NULL; } void ShaderTextureFunctionCase::setupUniforms (int programID, const tcu::Vec4&) { const glw::Functions& gl = m_renderCtx.getFunctions(); gl.uniform1i(gl.getUniformLocation(programID, "u_sampler"), 0); } ShaderTextureFunctionTests::ShaderTextureFunctionTests (Context& context) : TestCaseGroup(context, "texture_functions", "Texture Access Function Tests") { } ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void) { } struct TexFuncCaseSpec { const char* name; TextureLookupSpec lookupSpec; TextureSpec texSpec; TexEvalFunc evalFunc; }; #define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, TEXSPEC, EVALFUNC) \ { #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD), TEXSPEC, EVALFUNC } static void createCaseGroup (TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases, bool isVertex) { tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc); parent->addChild(group); for (int ndx = 0; ndx < numCases; ndx++) group->addChild(new ShaderTextureFunctionCase(parent->getContext(), cases[ndx].name, "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, isVertex)); } void ShaderTextureFunctionTests::init (void) { // Samplers static const tcu::Sampler samplerLinearNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR); static const tcu::Sampler samplerLinearMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR); // Default textures. // Type Format DataType W H L Sampler static const TextureSpec tex2D (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap); static const TextureSpec tex2DMipmap (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap); static const TextureSpec texCube (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap); static const TextureSpec texCubeMipmap (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap); // Vertex cases static const TexFuncCaseSpec vertexCases[] = { // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc 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), // 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), 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), 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), 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), // 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), // 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), 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), 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), 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), // 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), 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), }; createCaseGroup(this, "vertex", "Vertex Shader Texture Lookups", &vertexCases[0], DE_LENGTH_OF_ARRAY(vertexCases), true); // Fragment cases static const TexFuncCaseSpec fragmentCases[] = { // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc 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), 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), 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), 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), 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), 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), 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), 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) }; createCaseGroup(this, "fragment", "Fragment Shader Texture Lookups", &fragmentCases[0], DE_LENGTH_OF_ARRAY(fragmentCases), false); // Negative cases. { gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo()); std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/invalid_texture_functions.test"); tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, "invalid", "Invalid texture function usage", negativeCases); addChild(group); } } } // Functional } // gles3 } // deqp