1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 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 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 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. 18 * 19 *//*! 20 * \file 21 * \brief Texture access function tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es2fShaderTextureFunctionTests.hpp" 25#include "glsShaderRenderCase.hpp" 26#include "glsShaderLibrary.hpp" 27#include "gluTexture.hpp" 28#include "gluTextureUtil.hpp" 29#include "tcuTextureUtil.hpp" 30#include "tcuMatrix.hpp" 31#include "tcuMatrixUtil.hpp" 32 33#include <sstream> 34 35#include "glwEnums.hpp" 36#include "glwFunctions.hpp" 37 38namespace deqp 39{ 40namespace gles2 41{ 42namespace Functional 43{ 44 45namespace 46{ 47 48enum Function 49{ 50 FUNCTION_TEXTURE = 0, //!< texture(), textureOffset() 51 FUNCTION_TEXTUREPROJ, //!< textureProj(), textureProjOffset() 52 FUNCTION_TEXTUREPROJ3, //!< textureProj(sampler2D, vec3) 53 FUNCTION_TEXTURELOD, // ... 54 FUNCTION_TEXTUREPROJLOD, 55 FUNCTION_TEXTUREPROJLOD3, //!< textureProjLod(sampler2D, vec3) 56 57 FUNCTION_LAST 58}; 59 60inline bool functionHasProj (Function function) 61{ 62 return function == FUNCTION_TEXTUREPROJ || 63 function == FUNCTION_TEXTUREPROJ3 || 64 function == FUNCTION_TEXTUREPROJLOD || 65 function == FUNCTION_TEXTUREPROJLOD3; 66} 67 68inline bool functionHasLod (Function function) 69{ 70 return function == FUNCTION_TEXTURELOD || 71 function == FUNCTION_TEXTUREPROJLOD || 72 function == FUNCTION_TEXTUREPROJLOD3; 73} 74 75struct TextureLookupSpec 76{ 77 Function function; 78 79 tcu::Vec4 minCoord; 80 tcu::Vec4 maxCoord; 81 82 // Bias 83 bool useBias; 84 85 // Bias or Lod for *Lod* functions 86 float minLodBias; 87 float maxLodBias; 88 89 TextureLookupSpec (void) 90 : function (FUNCTION_LAST) 91 , minCoord (0.0f) 92 , maxCoord (1.0f) 93 , useBias (false) 94 , minLodBias (0.0f) 95 , maxLodBias (0.0f) 96 { 97 } 98 99 TextureLookupSpec (Function function_, 100 const tcu::Vec4& minCoord_, 101 const tcu::Vec4& maxCoord_, 102 bool useBias_, 103 float minLodBias_, 104 float maxLodBias_) 105 : function (function_) 106 , minCoord (minCoord_) 107 , maxCoord (maxCoord_) 108 , useBias (useBias_) 109 , minLodBias (minLodBias_) 110 , maxLodBias (maxLodBias_) 111 { 112 } 113}; 114 115enum TextureType 116{ 117 TEXTURETYPE_2D, 118 TEXTURETYPE_CUBE_MAP, 119 120 TEXTURETYPE_LAST 121}; 122 123struct TextureSpec 124{ 125 TextureType type; //!< Texture type (2D, cubemap, ...) 126 deUint32 format; 127 deUint32 dataType; 128 int width; 129 int height; 130 int numLevels; 131 tcu::Sampler sampler; 132 133 TextureSpec (void) 134 : type (TEXTURETYPE_LAST) 135 , format (GL_NONE) 136 , dataType (GL_NONE) 137 , width (0) 138 , height (0) 139 , numLevels (0) 140 { 141 } 142 143 TextureSpec (TextureType type_, 144 deUint32 format_, 145 deUint32 dataType_, 146 int width_, 147 int height_, 148 int numLevels_, 149 const tcu::Sampler& sampler_) 150 : type (type_) 151 , format (format_) 152 , dataType (dataType_) 153 , width (width_) 154 , height (height_) 155 , numLevels (numLevels_) 156 , sampler (sampler_) 157 { 158 } 159}; 160 161struct TexLookupParams 162{ 163 float lod; 164 tcu::Vec4 scale; 165 tcu::Vec4 bias; 166 167 TexLookupParams (void) 168 : lod (0.0f) 169 , scale (1.0f) 170 , bias (0.0f) 171 { 172 } 173}; 174 175} // anonymous 176 177using tcu::Vec2; 178using tcu::Vec3; 179using tcu::Vec4; 180using tcu::IVec2; 181using tcu::IVec3; 182using tcu::IVec4; 183 184inline float computeLodFromDerivates (float dudx, float dvdx, float dudy, float dvdy) 185{ 186 float p = de::max(deFloatSqrt(dudx*dudx + dvdx*dvdx), deFloatSqrt(dudy*dudy + dvdy*dvdy)); 187 return deFloatLog2(p); 188} 189 190typedef void (*TexEvalFunc) (gls::ShaderEvalContext& c, const TexLookupParams& lookupParams); 191 192inline 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); } 193inline 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); } 194 195// Eval functions. 196static 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; } 197static 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; } 198 199static 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; } 200static 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; } 201 202static 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; } 203static 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; } 204static 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; } 205static 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; } 206 207static 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; } 208static 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; } 209 210static 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; } 211static 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; } 212 213class TexLookupEvaluator : public gls::ShaderEvaluator 214{ 215public: 216 TexLookupEvaluator (TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {} 217 218 virtual void evaluate (gls::ShaderEvalContext& ctx) { m_evalFunc(ctx, m_lookupParams); } 219 220private: 221 TexEvalFunc m_evalFunc; 222 const TexLookupParams& m_lookupParams; 223}; 224 225class ShaderTextureFunctionCase : public gls::ShaderRenderCase 226{ 227public: 228 ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase); 229 ~ShaderTextureFunctionCase (void); 230 231 void init (void); 232 void deinit (void); 233 234protected: 235 void setupUniforms (int programID, const tcu::Vec4& constCoords); 236 237private: 238 void initTexture (void); 239 void initShaderSources (void); 240 241 TextureLookupSpec m_lookupSpec; 242 TextureSpec m_textureSpec; 243 244 TexLookupParams m_lookupParams; 245 TexLookupEvaluator m_evaluator; 246 247 glu::Texture2D* m_texture2D; 248 glu::TextureCube* m_textureCube; 249}; 250 251ShaderTextureFunctionCase::ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase) 252 : gls::ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator) 253 , m_lookupSpec (lookup) 254 , m_textureSpec (texture) 255 , m_evaluator (evalFunc, m_lookupParams) 256 , m_texture2D (DE_NULL) 257 , m_textureCube (DE_NULL) 258{ 259} 260 261ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void) 262{ 263 delete m_texture2D; 264 delete m_textureCube; 265} 266 267void ShaderTextureFunctionCase::init (void) 268{ 269 if (m_isVertexCase) 270 { 271 const glw::Functions& gl = m_renderCtx.getFunctions(); 272 int numVertexUnits = 0; 273 gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexUnits); 274 if (numVertexUnits < 1) 275 throw tcu::NotSupportedError("Vertex shader texture access is not supported"); 276 } 277 278 { 279 // Base coord scale & bias 280 Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord; 281 Vec4 b = m_lookupSpec.minCoord; 282 283 float baseCoordTrans[] = 284 { 285 s.x(), 0.0f, 0.f, b.x(), 286 0.f, s.y(), 0.f, b.y(), 287 s.z()/2.f, -s.z()/2.f, 0.f, s.z()/2.f + b.z(), 288 -s.w()/2.f, s.w()/2.f, 0.f, s.w()/2.f + b.w() 289 }; 290 291 m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans)); 292 } 293 294 if (functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias) 295 { 296 float s = m_lookupSpec.maxLodBias-m_lookupSpec.minLodBias; 297 float b = m_lookupSpec.minLodBias; 298 float lodCoordTrans[] = 299 { 300 s/2.0f, s/2.0f, 0.f, b, 301 0.0f, 0.0f, 0.0f, 0.0f, 302 0.0f, 0.0f, 0.0f, 0.0f, 303 0.0f, 0.0f, 0.0f, 0.0f 304 }; 305 306 m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans)); 307 } 308 309 initShaderSources(); 310 initTexture(); 311 312 gls::ShaderRenderCase::init(); 313} 314 315void ShaderTextureFunctionCase::initTexture (void) 316{ 317 static const IVec4 texCubeSwz[] = 318 { 319 IVec4(0,0,1,1), 320 IVec4(1,1,0,0), 321 IVec4(0,1,0,1), 322 IVec4(1,0,1,0), 323 IVec4(0,1,1,0), 324 IVec4(1,0,0,1) 325 }; 326 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST); 327 328 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType); 329 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); 330 tcu::IVec2 viewportSize = getViewportSize(); 331 bool isProj = functionHasProj(m_lookupSpec.function); 332 float proj = isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f; 333 334 switch (m_textureSpec.type) 335 { 336 case TEXTURETYPE_2D: 337 { 338 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); 339 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 340 Vec4 cBias = fmtInfo.valueMin; 341 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); 342 343 m_texture2D = new glu::Texture2D(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width, m_textureSpec.height); 344 for (int level = 0; level < m_textureSpec.numLevels; level++) 345 { 346 float fA = level*cStep; 347 float fB = 1.0f-fA; 348 Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB); 349 Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA); 350 351 m_texture2D->getRefTexture().allocLevel(level); 352 tcu::fillWithGrid(m_texture2D->getRefTexture().getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB); 353 } 354 m_texture2D->upload(); 355 356 // Compute LOD. 357 float dudx = (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*m_textureSpec.width / (float)viewportSize[0]; 358 float dvdy = (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*m_textureSpec.height / (float)viewportSize[1]; 359 m_lookupParams.lod = computeLodFromDerivates(dudx, 0.0f, 0.0f, dvdy); 360 361 // Append to texture list. 362 m_textures.push_back(gls::TextureBinding(m_texture2D, m_textureSpec.sampler)); 363 break; 364 } 365 366 case TEXTURETYPE_CUBE_MAP: 367 { 368 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1); 369 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin; 370 Vec4 cBias = fmtInfo.valueMin; 371 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4); 372 373 DE_ASSERT(m_textureSpec.width == m_textureSpec.height); 374 m_textureCube = new glu::TextureCube(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width); 375 for (int level = 0; level < m_textureSpec.numLevels; level++) 376 { 377 float fA = level*cStep; 378 float fB = 1.0f-fA; 379 Vec2 f (fA, fB); 380 381 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 382 { 383 const IVec4& swzA = texCubeSwz[face]; 384 IVec4 swzB = 1-swzA; 385 Vec4 colorA = cBias + cScale*f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]); 386 Vec4 colorB = cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]); 387 388 m_textureCube->getRefTexture().allocLevel((tcu::CubeFace)face, level); 389 tcu::fillWithGrid(m_textureCube->getRefTexture().getLevelFace(level, (tcu::CubeFace)face), de::max(1, baseCellSize>>level), colorA, colorB); 390 } 391 } 392 m_textureCube->upload(); 393 394 // Compute LOD \note Assumes that only single side is accessed and R is constant major axis. 395 DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005); 396 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])); 397 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])); 398 399 tcu::CubeFaceFloatCoords c00 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); 400 tcu::CubeFaceFloatCoords c10 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.maxCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); 401 tcu::CubeFaceFloatCoords c01 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.maxCoord[1]*proj, m_lookupSpec.minCoord[2]*proj)); 402 float dudx = (c10.s - c00.s)*m_textureSpec.width / (float)viewportSize[0]; 403 float dvdy = (c01.t - c00.t)*m_textureSpec.height / (float)viewportSize[1]; 404 405 m_lookupParams.lod = computeLodFromDerivates(dudx, 0.0f, 0.0f, dvdy); 406 407 m_textures.push_back(gls::TextureBinding(m_textureCube, m_textureSpec.sampler)); 408 break; 409 } 410 411 default: 412 DE_ASSERT(DE_FALSE); 413 } 414 415 // Set lookup scale & bias 416 m_lookupParams.scale = fmtInfo.lookupScale; 417 m_lookupParams.bias = fmtInfo.lookupBias; 418} 419 420void ShaderTextureFunctionCase::initShaderSources (void) 421{ 422 Function function = m_lookupSpec.function; 423 bool isVtxCase = m_isVertexCase; 424 bool isProj = functionHasProj(function); 425 bool is2DProj4 = m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD); 426 bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias; 427 int texCoordComps = m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3; 428 int extraCoordComps = isProj ? (is2DProj4 ? 2 : 1) : 0; 429 glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps+extraCoordComps); 430 glu::Precision coordPrec = glu::PRECISION_MEDIUMP; 431 const char* coordTypeName = glu::getDataTypeName(coordType); 432 const char* coordPrecName = glu::getPrecisionName(coordPrec); 433 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType); 434 glu::DataType samplerType = glu::TYPE_LAST; 435 const char* baseFuncName = m_textureSpec.type == TEXTURETYPE_2D ? "texture2D" : "textureCube"; 436 const char* funcExt = DE_NULL; 437 438 switch (m_textureSpec.type) 439 { 440 case TEXTURETYPE_2D: samplerType = glu::getSampler2DType(texFmt); break; 441 case TEXTURETYPE_CUBE_MAP: samplerType = glu::getSamplerCubeType(texFmt); break; 442 default: 443 DE_ASSERT(DE_FALSE); 444 } 445 446 switch (m_lookupSpec.function) 447 { 448 case FUNCTION_TEXTURE: funcExt = ""; break; 449 case FUNCTION_TEXTUREPROJ: funcExt = "Proj"; break; 450 case FUNCTION_TEXTUREPROJ3: funcExt = "Proj"; break; 451 case FUNCTION_TEXTURELOD: funcExt = "Lod"; break; 452 case FUNCTION_TEXTUREPROJLOD: funcExt = "ProjLod"; break; 453 case FUNCTION_TEXTUREPROJLOD3: funcExt = "ProjLod"; break; 454 default: 455 DE_ASSERT(DE_FALSE); 456 } 457 458 std::ostringstream vert; 459 std::ostringstream frag; 460 std::ostringstream& op = isVtxCase ? vert : frag; 461 462 vert << "attribute highp vec4 a_position;\n" 463 << "attribute " << coordPrecName << " " << coordTypeName << " a_in0;\n"; 464 465 if (hasLodBias) 466 vert << "attribute " << coordPrecName << " float a_in1;\n"; 467 468 if (isVtxCase) 469 { 470 vert << "varying mediump vec4 v_color;\n"; 471 frag << "varying mediump vec4 v_color;\n"; 472 } 473 else 474 { 475 vert << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; 476 frag << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n"; 477 478 if (hasLodBias) 479 { 480 vert << "varying " << coordPrecName << " float v_lodBias;\n"; 481 frag << "varying " << coordPrecName << " float v_lodBias;\n"; 482 } 483 } 484 485 // Uniforms 486 op << "uniform lowp " << glu::getDataTypeName(samplerType) << " u_sampler;\n"; 487 488 vert << "\nvoid main()\n{\n" 489 << "\tgl_Position = a_position;\n"; 490 frag << "\nvoid main()\n{\n"; 491 492 if (isVtxCase) 493 vert << "\tv_color = "; 494 else 495 frag << "\tgl_FragColor = "; 496 497 // Op. 498 { 499 const char* texCoord = isVtxCase ? "a_in0" : "v_texCoord"; 500 const char* lodBias = isVtxCase ? "a_in1" : "v_lodBias"; 501 502 op << baseFuncName << funcExt; 503 op << "(u_sampler, " << texCoord; 504 505 if (functionHasLod(function) || m_lookupSpec.useBias) 506 op << ", " << lodBias; 507 508 op << ");\n"; 509 } 510 511 if (isVtxCase) 512 frag << "\tgl_FragColor = v_color;\n"; 513 else 514 { 515 vert << "\tv_texCoord = a_in0;\n"; 516 517 if (hasLodBias) 518 vert << "\tv_lodBias = a_in1;\n"; 519 } 520 521 vert << "}\n"; 522 frag << "}\n"; 523 524 m_vertShaderSource = vert.str(); 525 m_fragShaderSource = frag.str(); 526} 527 528void ShaderTextureFunctionCase::deinit (void) 529{ 530 gls::ShaderRenderCase::deinit(); 531 532 delete m_texture2D; 533 delete m_textureCube; 534 535 m_texture2D = DE_NULL; 536 m_textureCube = DE_NULL; 537} 538 539void ShaderTextureFunctionCase::setupUniforms (int programID, const tcu::Vec4&) 540{ 541 const glw::Functions& gl = m_renderCtx.getFunctions(); 542 gl.uniform1i(gl.getUniformLocation(programID, "u_sampler"), 0); 543} 544 545ShaderTextureFunctionTests::ShaderTextureFunctionTests (Context& context) 546 : TestCaseGroup(context, "texture_functions", "Texture Access Function Tests") 547{ 548} 549 550ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void) 551{ 552} 553 554struct TexFuncCaseSpec 555{ 556 const char* name; 557 TextureLookupSpec lookupSpec; 558 TextureSpec texSpec; 559 TexEvalFunc evalFunc; 560}; 561 562#define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, TEXSPEC, EVALFUNC) \ 563 { #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD), TEXSPEC, EVALFUNC } 564 565static void createCaseGroup (TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases, bool isVertex) 566{ 567 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc); 568 parent->addChild(group); 569 570 for (int ndx = 0; ndx < numCases; ndx++) 571 group->addChild(new ShaderTextureFunctionCase(parent->getContext(), cases[ndx].name, "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, isVertex)); 572} 573 574void ShaderTextureFunctionTests::init (void) 575{ 576 // Samplers 577 static const tcu::Sampler samplerLinearNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, 578 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR); 579 static const tcu::Sampler samplerLinearMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, 580 tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR); 581 582 // Default textures. 583 // Type Format DataType W H L Sampler 584 static const TextureSpec tex2D (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap); 585 static const TextureSpec tex2DMipmap (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap); 586 587 static const TextureSpec texCube (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap); 588 static const TextureSpec texCubeMipmap (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap); 589 590 // Vertex cases 591 static const TexFuncCaseSpec vertexCases[] = 592 { 593 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc 594 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), 595// 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), 596 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), 597 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), 598 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), 599// 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), 600// 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), 601 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), 602 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), 603 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), 604// 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), 605 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), 606 }; 607 createCaseGroup(this, "vertex", "Vertex Shader Texture Lookups", &vertexCases[0], DE_LENGTH_OF_ARRAY(vertexCases), true); 608 609 // Fragment cases 610 static const TexFuncCaseSpec fragmentCases[] = 611 { 612 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc 613 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), 614 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), 615 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), 616 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), 617 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), 618 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), 619 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), 620 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) 621 }; 622 createCaseGroup(this, "fragment", "Fragment Shader Texture Lookups", &fragmentCases[0], DE_LENGTH_OF_ARRAY(fragmentCases), false); 623 624 // Negative cases. 625 { 626 gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo()); 627 std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/invalid_texture_functions.test"); 628 629 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, "invalid", "Invalid texture function usage", negativeCases); 630 addChild(group); 631 } 632} 633 634} // Functional 635} // gles3 636} // deqp 637